Merge "Add Rx RemoteMediator samples" into androidx-master-dev
diff --git a/activity/activity/api/api_lint.ignore b/activity/activity/api/api_lint.ignore
index d22641b..2784aac 100644
--- a/activity/activity/api/api_lint.ignore
+++ b/activity/activity/api/api_lint.ignore
@@ -3,10 +3,6 @@
ComponentActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead.
-KotlinOperator: androidx.activity.result.ActivityResultRegistry#invoke(int, androidx.activity.result.contract.ActivityResultContract<I,O>, I, androidx.core.app.ActivityOptionsCompat):
- Method can be invoked with function call syntax from Kotlin: `invoke` (this is usually desirable; just make sure it makes sense for this type of object)
-
-
MissingNullability: androidx.activity.ComponentActivity#startActivityForResult(android.content.Intent, int) parameter #0:
Missing nullability on parameter `intent` in method `startActivityForResult`
MissingNullability: androidx.activity.ComponentActivity#startActivityForResult(android.content.Intent, int, android.os.Bundle) parameter #0:
diff --git a/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml b/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml
index b89cf16..5f8aea8 100644
--- a/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml
+++ b/ads/ads-identifier-benchmark/src/androidTest/AndroidManifest.xml
@@ -24,5 +24,8 @@
android:name=".AdsIdentifierBenchmarkApplication"
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/annotation/annotation-experimental/api/1.1.0-alpha01.txt b/annotation/annotation-experimental/api/1.1.0-alpha01.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/1.1.0-alpha01.txt
+++ b/annotation/annotation-experimental/api/1.1.0-alpha01.txt
@@ -6,6 +6,8 @@
}
public enum Experimental.Level {
+ method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.annotation.experimental.Experimental.Level[] values();
enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
}
diff --git a/annotation/annotation-experimental/api/current.txt b/annotation/annotation-experimental/api/current.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/current.txt
+++ b/annotation/annotation-experimental/api/current.txt
@@ -6,6 +6,8 @@
}
public enum Experimental.Level {
+ method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.annotation.experimental.Experimental.Level[] values();
enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
}
diff --git a/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt b/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt
+++ b/annotation/annotation-experimental/api/public_plus_experimental_1.1.0-alpha01.txt
@@ -6,6 +6,8 @@
}
public enum Experimental.Level {
+ method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.annotation.experimental.Experimental.Level[] values();
enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
}
diff --git a/annotation/annotation-experimental/api/public_plus_experimental_current.txt b/annotation/annotation-experimental/api/public_plus_experimental_current.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/public_plus_experimental_current.txt
+++ b/annotation/annotation-experimental/api/public_plus_experimental_current.txt
@@ -6,6 +6,8 @@
}
public enum Experimental.Level {
+ method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.annotation.experimental.Experimental.Level[] values();
enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
}
diff --git a/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt b/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt
+++ b/annotation/annotation-experimental/api/restricted_1.1.0-alpha01.txt
@@ -6,6 +6,8 @@
}
public enum Experimental.Level {
+ method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.annotation.experimental.Experimental.Level[] values();
enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
}
diff --git a/annotation/annotation-experimental/api/restricted_current.txt b/annotation/annotation-experimental/api/restricted_current.txt
index c4e699b..e854aa6 100644
--- a/annotation/annotation-experimental/api/restricted_current.txt
+++ b/annotation/annotation-experimental/api/restricted_current.txt
@@ -6,6 +6,8 @@
}
public enum Experimental.Level {
+ method public static androidx.annotation.experimental.Experimental.Level valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.annotation.experimental.Experimental.Level[] values();
enum_constant public static final androidx.annotation.experimental.Experimental.Level ERROR;
enum_constant public static final androidx.annotation.experimental.Experimental.Level WARNING;
}
diff --git a/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml b/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml
index 1302397..1c5fab4 100644
--- a/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml
+++ b/appcompat/appcompat-benchmark/src/androidTest/AndroidManifest.xml
@@ -23,6 +23,9 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
<activity android:name="androidx.appcompat.app.AppCompatActivity"
android:theme="@style/Theme.AppCompat"/>
</application>
diff --git a/appcompat/appcompat/api/1.3.0-alpha01.txt b/appcompat/appcompat/api/1.3.0-alpha01.txt
index dc3c5ab..89aae44 100644
--- a/appcompat/appcompat/api/1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/1.3.0-alpha01.txt
@@ -449,11 +449,11 @@
ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
ctor public ActionMenuView.LayoutParams(int, int);
- field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
- field @android.view.ViewDebug.ExportedProperty public boolean expandable;
- field @android.view.ViewDebug.ExportedProperty public int extraPixels;
- field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
- field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+ field public int cellsUsed;
+ field public boolean expandable;
+ field public int extraPixels;
+ field public boolean isOverflowButton;
+ field public boolean preventEdgeOffset;
}
public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/api_lint.ignore b/appcompat/appcompat/api/api_lint.ignore
index fd01b04a8..edddedd 100644
--- a/appcompat/appcompat/api/api_lint.ignore
+++ b/appcompat/appcompat/api/api_lint.ignore
@@ -613,8 +613,6 @@
Missing nullability on method `onCreateInputConnection` return
MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo) parameter #0:
Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
-MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
MissingNullability: androidx.appcompat.widget.AppCompatAutoCompleteTextView#setTextAppearance(android.content.Context, int) parameter #0:
@@ -625,14 +623,10 @@
Missing nullability on parameter `info` in method `onInitializeAccessibilityNodeInfo`
MissingNullability: androidx.appcompat.widget.AppCompatButton#onTextChanged(CharSequence, int, int, int) parameter #0:
Missing nullability on parameter `text` in method `onTextChanged`
-MissingNullability: androidx.appcompat.widget.AppCompatButton#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatButton#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
MissingNullability: androidx.appcompat.widget.AppCompatButton#setTextAppearance(android.content.Context, int) parameter #0:
Missing nullability on parameter `context` in method `setTextAppearance`
-MissingNullability: androidx.appcompat.widget.AppCompatCheckBox#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatCheckBox#setButtonDrawable(android.graphics.drawable.Drawable) parameter #0:
Missing nullability on parameter `buttonDrawable` in method `setButtonDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatCheckedTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo):
@@ -647,26 +641,18 @@
Missing nullability on method `onCreateInputConnection` return
MissingNullability: androidx.appcompat.widget.AppCompatEditText#onCreateInputConnection(android.view.inputmethod.EditorInfo) parameter #0:
Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
-MissingNullability: androidx.appcompat.widget.AppCompatEditText#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatEditText#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
MissingNullability: androidx.appcompat.widget.AppCompatEditText#setTextAppearance(android.content.Context, int) parameter #0:
Missing nullability on parameter `context` in method `setTextAppearance`
-MissingNullability: androidx.appcompat.widget.AppCompatImageButton#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatImageButton#setImageBitmap(android.graphics.Bitmap) parameter #0:
Missing nullability on parameter `bm` in method `setImageBitmap`
-MissingNullability: androidx.appcompat.widget.AppCompatImageView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatImageView#setImageBitmap(android.graphics.Bitmap) parameter #0:
Missing nullability on parameter `bm` in method `setImageBitmap`
MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo):
Missing nullability on method `onCreateInputConnection` return
MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#onCreateInputConnection(android.view.inputmethod.EditorInfo) parameter #0:
Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
-MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView#setTextAppearance(android.content.Context, int) parameter #0:
Missing nullability on parameter `context` in method `setTextAppearance`
MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#AppCompatRadioButton(android.content.Context) parameter #0:
@@ -675,8 +661,6 @@
Missing nullability on parameter `context` in method `AppCompatRadioButton`
MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#AppCompatRadioButton(android.content.Context, android.util.AttributeSet, int) parameter #0:
Missing nullability on parameter `context` in method `AppCompatRadioButton`
-MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatRadioButton#setButtonDrawable(android.graphics.drawable.Drawable) parameter #0:
Missing nullability on parameter `buttonDrawable` in method `setButtonDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatSeekBar#onDraw(android.graphics.Canvas) parameter #0:
@@ -697,8 +681,6 @@
Missing nullability on parameter `event` in method `onTouchEvent`
MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setAdapter(android.widget.SpinnerAdapter) parameter #0:
Missing nullability on parameter `adapter` in method `setAdapter`
-MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setPopupBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
Missing nullability on parameter `background` in method `setPopupBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatSpinner#setPrompt(CharSequence) parameter #0:
@@ -711,8 +693,6 @@
Missing nullability on parameter `outAttrs` in method `onCreateInputConnection`
MissingNullability: androidx.appcompat.widget.AppCompatTextView#onTextChanged(CharSequence, int, int, int) parameter #0:
Missing nullability on parameter `text` in method `onTextChanged`
-MissingNullability: androidx.appcompat.widget.AppCompatTextView#setBackgroundDrawable(android.graphics.drawable.Drawable) parameter #0:
- Missing nullability on parameter `background` in method `setBackgroundDrawable`
MissingNullability: androidx.appcompat.widget.AppCompatTextView#setCustomSelectionActionModeCallback(android.view.ActionMode.Callback) parameter #0:
Missing nullability on parameter `actionModeCallback` in method `setCustomSelectionActionModeCallback`
MissingNullability: androidx.appcompat.widget.AppCompatTextView#setTextAppearance(android.content.Context, int) parameter #0:
diff --git a/appcompat/appcompat/api/current.txt b/appcompat/appcompat/api/current.txt
index dc3c5ab..89aae44 100644
--- a/appcompat/appcompat/api/current.txt
+++ b/appcompat/appcompat/api/current.txt
@@ -449,11 +449,11 @@
ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
ctor public ActionMenuView.LayoutParams(int, int);
- field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
- field @android.view.ViewDebug.ExportedProperty public boolean expandable;
- field @android.view.ViewDebug.ExportedProperty public int extraPixels;
- field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
- field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+ field public int cellsUsed;
+ field public boolean expandable;
+ field public int extraPixels;
+ field public boolean isOverflowButton;
+ field public boolean preventEdgeOffset;
}
public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt b/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
index 09e7731..dca14b8 100644
--- a/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_1.3.0-alpha01.txt
@@ -449,11 +449,11 @@
ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
ctor public ActionMenuView.LayoutParams(int, int);
- field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
- field @android.view.ViewDebug.ExportedProperty public boolean expandable;
- field @android.view.ViewDebug.ExportedProperty public int extraPixels;
- field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
- field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+ field public int cellsUsed;
+ field public boolean expandable;
+ field public int extraPixels;
+ field public boolean isOverflowButton;
+ field public boolean preventEdgeOffset;
}
public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/public_plus_experimental_current.txt b/appcompat/appcompat/api/public_plus_experimental_current.txt
index 09e7731..dca14b8 100644
--- a/appcompat/appcompat/api/public_plus_experimental_current.txt
+++ b/appcompat/appcompat/api/public_plus_experimental_current.txt
@@ -449,11 +449,11 @@
ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
ctor public ActionMenuView.LayoutParams(int, int);
- field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
- field @android.view.ViewDebug.ExportedProperty public boolean expandable;
- field @android.view.ViewDebug.ExportedProperty public int extraPixels;
- field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
- field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+ field public int cellsUsed;
+ field public boolean expandable;
+ field public int extraPixels;
+ field public boolean isOverflowButton;
+ field public boolean preventEdgeOffset;
}
public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt b/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
index 6f63cec..a210c6c6 100644
--- a/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
+++ b/appcompat/appcompat/api/restricted_1.3.0-alpha01.txt
@@ -936,14 +936,14 @@
method public int getGroupId();
method public android.graphics.drawable.Drawable! getIcon();
method public android.content.Intent! getIntent();
- method @android.view.ViewDebug.CapturedViewProperty public int getItemId();
+ method public int getItemId();
method public android.view.ContextMenu.ContextMenuInfo! getMenuInfo();
method public char getNumericShortcut();
method public int getOrder();
method public int getOrdering();
method public android.view.SubMenu! getSubMenu();
method public androidx.core.view.ActionProvider! getSupportActionProvider();
- method @android.view.ViewDebug.CapturedViewProperty public CharSequence! getTitle();
+ method public CharSequence! getTitle();
method public CharSequence! getTitleCondensed();
method public boolean hasCollapsibleActionView();
method public boolean hasSubMenu();
@@ -1295,11 +1295,11 @@
ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
ctor public ActionMenuView.LayoutParams(int, int);
- field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
- field @android.view.ViewDebug.ExportedProperty public boolean expandable;
- field @android.view.ViewDebug.ExportedProperty public int extraPixels;
- field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
- field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+ field public int cellsUsed;
+ field public boolean expandable;
+ field public int extraPixels;
+ field public boolean isOverflowButton;
+ field public boolean preventEdgeOffset;
}
public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appcompat/appcompat/api/restricted_current.txt b/appcompat/appcompat/api/restricted_current.txt
index 6f63cec..a210c6c6 100644
--- a/appcompat/appcompat/api/restricted_current.txt
+++ b/appcompat/appcompat/api/restricted_current.txt
@@ -936,14 +936,14 @@
method public int getGroupId();
method public android.graphics.drawable.Drawable! getIcon();
method public android.content.Intent! getIntent();
- method @android.view.ViewDebug.CapturedViewProperty public int getItemId();
+ method public int getItemId();
method public android.view.ContextMenu.ContextMenuInfo! getMenuInfo();
method public char getNumericShortcut();
method public int getOrder();
method public int getOrdering();
method public android.view.SubMenu! getSubMenu();
method public androidx.core.view.ActionProvider! getSupportActionProvider();
- method @android.view.ViewDebug.CapturedViewProperty public CharSequence! getTitle();
+ method public CharSequence! getTitle();
method public CharSequence! getTitleCondensed();
method public boolean hasCollapsibleActionView();
method public boolean hasSubMenu();
@@ -1295,11 +1295,11 @@
ctor public ActionMenuView.LayoutParams(android.view.ViewGroup.LayoutParams!);
ctor public ActionMenuView.LayoutParams(androidx.appcompat.widget.ActionMenuView.LayoutParams!);
ctor public ActionMenuView.LayoutParams(int, int);
- field @android.view.ViewDebug.ExportedProperty public int cellsUsed;
- field @android.view.ViewDebug.ExportedProperty public boolean expandable;
- field @android.view.ViewDebug.ExportedProperty public int extraPixels;
- field @android.view.ViewDebug.ExportedProperty public boolean isOverflowButton;
- field @android.view.ViewDebug.ExportedProperty public boolean preventEdgeOffset;
+ field public int cellsUsed;
+ field public boolean expandable;
+ field public int extraPixels;
+ field public boolean isOverflowButton;
+ field public boolean preventEdgeOffset;
}
public static interface ActionMenuView.OnMenuItemClickListener {
diff --git a/appsearch/appsearch/api/1.0.0-alpha01.txt b/appsearch/appsearch/api/1.0.0-alpha01.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/1.0.0-alpha01.txt
@@ -1,6 +1,27 @@
// Signature format: 3.0
package androidx.appsearch.app {
+ public final class AppSearchBatchResult<KeyType, ValueType> {
+ method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+ method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+ method public boolean isSuccess();
+ }
+
+ public final class AppSearchResult<ValueType> {
+ method public String? getErrorMessage();
+ method public int getResultCode();
+ method public ValueType? getResultValue();
+ method public boolean isSuccess();
+ field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+ field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+ field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+ field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+ field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+ }
+
public final class AppSearchSchema {
}
diff --git a/appsearch/appsearch/api/current.txt b/appsearch/appsearch/api/current.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/current.txt
+++ b/appsearch/appsearch/api/current.txt
@@ -1,6 +1,27 @@
// Signature format: 3.0
package androidx.appsearch.app {
+ public final class AppSearchBatchResult<KeyType, ValueType> {
+ method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+ method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+ method public boolean isSuccess();
+ }
+
+ public final class AppSearchResult<ValueType> {
+ method public String? getErrorMessage();
+ method public int getResultCode();
+ method public ValueType? getResultValue();
+ method public boolean isSuccess();
+ field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+ field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+ field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+ field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+ field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+ }
+
public final class AppSearchSchema {
}
diff --git a/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt b/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -1,6 +1,27 @@
// Signature format: 3.0
package androidx.appsearch.app {
+ public final class AppSearchBatchResult<KeyType, ValueType> {
+ method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+ method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+ method public boolean isSuccess();
+ }
+
+ public final class AppSearchResult<ValueType> {
+ method public String? getErrorMessage();
+ method public int getResultCode();
+ method public ValueType? getResultValue();
+ method public boolean isSuccess();
+ field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+ field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+ field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+ field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+ field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+ }
+
public final class AppSearchSchema {
}
diff --git a/appsearch/appsearch/api/public_plus_experimental_current.txt b/appsearch/appsearch/api/public_plus_experimental_current.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/public_plus_experimental_current.txt
+++ b/appsearch/appsearch/api/public_plus_experimental_current.txt
@@ -1,6 +1,27 @@
// Signature format: 3.0
package androidx.appsearch.app {
+ public final class AppSearchBatchResult<KeyType, ValueType> {
+ method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+ method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+ method public boolean isSuccess();
+ }
+
+ public final class AppSearchResult<ValueType> {
+ method public String? getErrorMessage();
+ method public int getResultCode();
+ method public ValueType? getResultValue();
+ method public boolean isSuccess();
+ field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+ field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+ field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+ field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+ field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+ }
+
public final class AppSearchSchema {
}
diff --git a/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt b/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
+++ b/appsearch/appsearch/api/restricted_1.0.0-alpha01.txt
@@ -1,6 +1,27 @@
// Signature format: 3.0
package androidx.appsearch.app {
+ public final class AppSearchBatchResult<KeyType, ValueType> {
+ method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+ method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+ method public boolean isSuccess();
+ }
+
+ public final class AppSearchResult<ValueType> {
+ method public String? getErrorMessage();
+ method public int getResultCode();
+ method public ValueType? getResultValue();
+ method public boolean isSuccess();
+ field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+ field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+ field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+ field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+ field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+ }
+
public final class AppSearchSchema {
}
diff --git a/appsearch/appsearch/api/restricted_current.txt b/appsearch/appsearch/api/restricted_current.txt
index 41e4226..84c5ef0 100644
--- a/appsearch/appsearch/api/restricted_current.txt
+++ b/appsearch/appsearch/api/restricted_current.txt
@@ -1,6 +1,27 @@
// Signature format: 3.0
package androidx.appsearch.app {
+ public final class AppSearchBatchResult<KeyType, ValueType> {
+ method public java.util.Map<KeyType!,androidx.appsearch.app.AppSearchResult<ValueType!>!> getFailures();
+ method public java.util.Map<KeyType!,ValueType!> getSuccesses();
+ method public boolean isSuccess();
+ }
+
+ public final class AppSearchResult<ValueType> {
+ method public String? getErrorMessage();
+ method public int getResultCode();
+ method public ValueType? getResultValue();
+ method public boolean isSuccess();
+ field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+ field public static final int RESULT_INVALID_ARGUMENT = 3; // 0x3
+ field public static final int RESULT_INVALID_SCHEMA = 7; // 0x7
+ field public static final int RESULT_IO_ERROR = 4; // 0x4
+ field public static final int RESULT_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_OUT_OF_SPACE = 5; // 0x5
+ field public static final int RESULT_UNKNOWN_ERROR = 1; // 0x1
+ }
+
public final class AppSearchSchema {
}
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java
index 16b51a7..1c52c2f 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchBatchResult.java
@@ -18,7 +18,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
import androidx.collection.ArrayMap;
import androidx.core.util.Preconditions;
@@ -30,9 +29,7 @@
*
* @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}.
* @param <ValueType> The type of result objects associated with the keys.
- * @hide
*/
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class AppSearchBatchResult<KeyType, ValueType> {
@NonNull private final Map<KeyType, ValueType> mSuccesses;
@NonNull private final Map<KeyType, AppSearchResult<ValueType>> mFailures;
@@ -75,7 +72,6 @@
* Asserts that this {@link AppSearchBatchResult} has no failures.
* @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void checkSuccess() {
if (!isSuccess()) {
throw new IllegalStateException("AppSearchBatchResult has failures: " + this);
@@ -93,6 +89,7 @@
*
* @param <KeyType> The type of keys.
* @param <ValueType> The type of result objects associated with the keys.
+ * @hide
*/
public static final class Builder<KeyType, ValueType> {
private final Map<KeyType, ValueType> mSuccesses = new ArrayMap<>();
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java
index 750542f..d2fd6be 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/app/AppSearchResult.java
@@ -19,7 +19,6 @@
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
import androidx.core.util.ObjectsCompat;
import java.lang.annotation.Retention;
@@ -29,11 +28,12 @@
* Information about the success or failure of an AppSearch call.
*
* @param <ValueType> The type of result object for successful calls.
- * @hide
*/
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class AppSearchResult<ValueType> {
- /** Result codes from {@link AppSearchManager} methods. */
+ /**
+ * Result codes from {@link AppSearchManager} methods.
+ * @hide
+ */
@IntDef(value = {
RESULT_OK,
RESULT_UNKNOWN_ERROR,
@@ -111,9 +111,10 @@
*
* <p>If {@link #isSuccess} is {@code false}, the result value is always {@code null}. The value
* may be {@code null} even if {@link #isSuccess} is {@code true}. See the documentation of the
- * particular {@link AppSearchManager} call producing this {@link AppSearchResult} for what is
+ * particular {@code AppSearchManager} call producing this {@link AppSearchResult} for what is
* returned by {@link #getResultValue}.
*/
+ // TODO(b/157082794): Linkify AppSearchManager once that API is public
@Nullable
public ValueType getResultValue() {
return mResultValue;
@@ -124,9 +125,10 @@
*
* <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}. The error
* message may be {@code null} even if {@link #isSuccess} is {@code false}. See the
- * documentation of the particular {@link AppSearchManager} call producing this
+ * documentation of the particular {@code AppSearchManager} call producing this
* {@link AppSearchResult} for what is returned by {@link #getErrorMessage}.
*/
+ // TODO(b/157082794): Linkify AppSearchManager once that API is public
@Nullable
public String getErrorMessage() {
return mErrorMessage;
@@ -136,7 +138,6 @@
* Asserts that this {@link AppSearchResult} is successful.
* @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void checkSuccess() {
if (!isSuccess()) {
throw new IllegalStateException("AppSearchResult is a failure: " + this);
@@ -171,14 +172,20 @@
return "[FAILURE(" + mResultCode + ")]: " + mErrorMessage;
}
- /** Creates a new successful {@link AppSearchResult}. */
+ /**
+ * Creates a new successful {@link AppSearchResult}.
+ * @hide
+ */
@NonNull
public static <ValueType> AppSearchResult<ValueType> newSuccessfulResult(
@Nullable ValueType value) {
return new AppSearchResult<>(RESULT_OK, value, /*errorMessage=*/ null);
}
- /** Creates a new failed {@link AppSearchResult}. */
+ /**
+ * Creates a new failed {@link AppSearchResult}.
+ * @hide
+ */
@NonNull
public static <ValueType> AppSearchResult<ValueType> newFailedResult(
@ResultCode int resultCode, @Nullable String errorMessage) {
diff --git a/autofill/autofill/api/1.1.0-alpha02.txt b/autofill/autofill/api/1.1.0-alpha02.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/1.1.0-alpha02.txt
+++ b/autofill/autofill/api/1.1.0-alpha02.txt
@@ -156,6 +156,7 @@
public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+ method public int getLayoutDirection();
method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+ method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/current.txt b/autofill/autofill/api/current.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/current.txt
+++ b/autofill/autofill/api/current.txt
@@ -156,6 +156,7 @@
public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+ method public int getLayoutDirection();
method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+ method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt b/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt
+++ b/autofill/autofill/api/public_plus_experimental_1.1.0-alpha02.txt
@@ -156,6 +156,7 @@
public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+ method public int getLayoutDirection();
method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+ method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/public_plus_experimental_current.txt b/autofill/autofill/api/public_plus_experimental_current.txt
index 7e4b270..d6f51b3 100644
--- a/autofill/autofill/api/public_plus_experimental_current.txt
+++ b/autofill/autofill/api/public_plus_experimental_current.txt
@@ -156,6 +156,7 @@
public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+ method public int getLayoutDirection();
method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -167,6 +168,7 @@
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+ method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/restricted_1.1.0-alpha02.txt b/autofill/autofill/api/restricted_1.1.0-alpha02.txt
index 79e5e66..78c7008 100644
--- a/autofill/autofill/api/restricted_1.1.0-alpha02.txt
+++ b/autofill/autofill/api/restricted_1.1.0-alpha02.txt
@@ -159,6 +159,7 @@
public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+ method public int getLayoutDirection();
method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -170,6 +171,7 @@
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+ method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/api/restricted_current.txt b/autofill/autofill/api/restricted_current.txt
index 79e5e66..78c7008 100644
--- a/autofill/autofill/api/restricted_current.txt
+++ b/autofill/autofill/api/restricted_current.txt
@@ -159,6 +159,7 @@
public static final class InlineSuggestionUi.Style implements androidx.autofill.inline.UiVersions.Style {
method public androidx.autofill.inline.common.ViewStyle? getChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getEndIconStyle();
+ method public int getLayoutDirection();
method public androidx.autofill.inline.common.ImageViewStyle? getSingleIconChipIconStyle();
method public androidx.autofill.inline.common.ViewStyle? getSingleIconChipStyle();
method public androidx.autofill.inline.common.ImageViewStyle? getStartIconStyle();
@@ -170,6 +171,7 @@
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style build();
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setEndIconStyle(androidx.autofill.inline.common.ImageViewStyle);
+ method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setLayoutDirection(int);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipIconStyle(androidx.autofill.inline.common.ImageViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setSingleIconChipStyle(androidx.autofill.inline.common.ViewStyle);
method public androidx.autofill.inline.v1.InlineSuggestionUi.Style.Builder setStartIconStyle(androidx.autofill.inline.common.ImageViewStyle);
diff --git a/autofill/autofill/src/androidTest/AndroidManifest.xml b/autofill/autofill/src/androidTest/AndroidManifest.xml
index 966f635..a7bf090 100644
--- a/autofill/autofill/src/androidTest/AndroidManifest.xml
+++ b/autofill/autofill/src/androidTest/AndroidManifest.xml
@@ -14,8 +14,10 @@
limitations under the License
-->
-<manifest package="androidx.autofill.tests">
- <application>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.autofill.tests">
+ <application
+ android:supportsRtl="true">
<activity xmlns:android="http://schemas.android.com/apk/res/android"
android:name="androidx.autofill.inline.InlineUiActivity">
</activity>
diff --git a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java
index 29c7d6b..7f8df02 100644
--- a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java
+++ b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/common/ViewStyleTest.java
@@ -99,4 +99,18 @@
// When both background and background color are set, the background color takes precedence.
TestUtils.verifyBackgroundColor(view, Color.YELLOW);
}
+
+ @Test
+ public void testStyleWithRtl() {
+ ViewStyle.Builder builder = new ViewStyle.Builder();
+ ViewStyle style = builder
+ .setPadding(1, 2, 3, 4)
+ .setLayoutMargin(5, 6, 7, 8)
+ .build();
+ View view = new View(mContext);
+ view.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+ style.applyStyleOnViewIfValid(view);
+ TestUtils.verifyPadding(view, 3, 2, 1, 4);
+ TestUtils.verifyLayoutMargin(view, 7, 6, 5, 8);
+ }
}
diff --git a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java
index bb7e554..78a2d4f 100644
--- a/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java
+++ b/autofill/autofill/src/androidTest/java/androidx/autofill/inline/v1/InlineSuggestionUiTest.java
@@ -225,7 +225,6 @@
assertEquals(TITLE, titleView.getText());
assertEquals(Color.BLUE, titleView.getCurrentTextColor());
-
TextView subtitleView =
mLinearLayout.findViewById(R.id.autofill_inline_suggestion_subtitle);
assertEquals(SUB_TITLE, subtitleView.getText());
@@ -239,6 +238,72 @@
TestUtils.verifyPadding(endIcon, 21, 22, 23, 24);
}
+ @Test
+ public void testRender_allWidgets_rtl() {
+ InlineSuggestionUi.Style style = new InlineSuggestionUi.Style.Builder()
+ .setLayoutDirection(View.LAYOUT_DIRECTION_RTL)
+ .setChipStyle(new ViewStyle.Builder().setPadding(11, 12, 13, 14).build())
+ .setStartIconStyle(new ImageViewStyle.Builder()
+ .setPadding(21, 22, 23, 24)
+ .setLayoutMargin(31, 32, 33, 34).build())
+ .setSingleIconChipStyle(new ViewStyle.Builder().setPadding(41, 42, 43, 44).build())
+ .setSingleIconChipIconStyle(new ImageViewStyle.Builder()
+ .setPadding(51, 52, 53, 54)
+ .setLayoutMargin(61, 62, 63, 64).build())
+ .build();
+ InlineSuggestionUi.Content contentAllWidgets = InlineSuggestionUi.newContentBuilder(
+ mAttributionIntent)
+ .setContentDescription("Content blabla")
+ .setTitle(TITLE)
+ .setSubtitle(SUB_TITLE)
+ .setStartIcon(Icon.createWithResource(mContext,
+ androidx.autofill.test.R.drawable.ic_settings))
+ .setEndIcon(Icon.createWithResource(mContext,
+ androidx.autofill.test.R.drawable.ic_settings)).build();
+ View view = InlineSuggestionUi.render(mContext, contentAllWidgets, style);
+ addView(view);
+
+ verifyVisibility(true, true, true, true);
+ TestUtils.verifyPadding(view, 13, 12, 11, 14);
+ assertEquals("Content blabla", view.getContentDescription());
+
+ ImageView startIcon =
+ mLinearLayout.findViewById(R.id.autofill_inline_suggestion_start_icon);
+ TestUtils.verifyPadding(startIcon, 23, 22, 21, 24);
+ TestUtils.verifyLayoutMargin(startIcon, 33, 32, 31, 34);
+ }
+
+ @Test
+ public void testRender_singleIcon_rtl() {
+ InlineSuggestionUi.Style style = new InlineSuggestionUi.Style.Builder()
+ .setLayoutDirection(View.LAYOUT_DIRECTION_RTL)
+ .setChipStyle(new ViewStyle.Builder().setPadding(11, 12, 13, 14).build())
+ .setStartIconStyle(new ImageViewStyle.Builder()
+ .setPadding(21, 22, 23, 24)
+ .setLayoutMargin(31, 32, 33, 34).build())
+ .setSingleIconChipStyle(new ViewStyle.Builder().setPadding(41, 42, 43, 44).build())
+ .setSingleIconChipIconStyle(new ImageViewStyle.Builder()
+ .setPadding(51, 52, 53, 54)
+ .setLayoutMargin(61, 62, 63, 64).build())
+ .build();
+ InlineSuggestionUi.Content contentSingleIcon = InlineSuggestionUi.newContentBuilder(
+ mAttributionIntent)
+ .setContentDescription("Content blabla")
+ .setStartIcon(Icon.createWithResource(mContext,
+ androidx.autofill.test.R.drawable.ic_settings)).build();
+ View view = InlineSuggestionUi.render(mContext, contentSingleIcon, style);
+ addView(view);
+
+ verifyVisibility(false, false, true, false);
+ TestUtils.verifyPadding(view, 43, 42, 41, 44);
+ assertEquals("Content blabla", view.getContentDescription());
+
+ ImageView startIcon =
+ mLinearLayout.findViewById(R.id.autofill_inline_suggestion_start_icon);
+ TestUtils.verifyPadding(startIcon, 53, 52, 51, 54);
+ TestUtils.verifyLayoutMargin(startIcon, 63, 62, 61, 64);
+ }
+
/** Below are tests for the Content class */
@Test
@@ -397,6 +462,35 @@
TestUtils.verifyBackgroundColor(endIconView, Color.RED);
}
+ @Test
+ public void testStyleWithRtl() {
+ InlineSuggestionUi.Style.Builder builder = new InlineSuggestionUi.Style.Builder();
+ InlineSuggestionUi.Style style = builder.setLayoutDirection(
+ View.LAYOUT_DIRECTION_RTL).build();
+
+ View suggestionView = LayoutInflater.from(mContext).inflate(
+ R.layout.autofill_inline_suggestion, null);
+ ImageView startIconView = suggestionView.findViewById(
+ R.id.autofill_inline_suggestion_start_icon);
+ startIconView.setVisibility(View.VISIBLE);
+ TextView titleView = suggestionView.findViewById(R.id.autofill_inline_suggestion_title);
+ titleView.setVisibility(View.VISIBLE);
+ TextView subtitleView = suggestionView.findViewById(
+ R.id.autofill_inline_suggestion_subtitle);
+ subtitleView.setVisibility(View.VISIBLE);
+ ImageView endIconView = suggestionView.findViewById(
+ R.id.autofill_inline_suggestion_end_icon);
+ endIconView.setVisibility(View.VISIBLE);
+
+ style.applyStyle(suggestionView, startIconView, titleView, subtitleView, endIconView);
+
+ assertEquals(View.LAYOUT_DIRECTION_RTL, suggestionView.getLayoutDirection());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, startIconView.getLayoutDirection());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, titleView.getLayoutDirection());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, subtitleView.getLayoutDirection());
+ assertEquals(View.LAYOUT_DIRECTION_RTL, endIconView.getLayoutDirection());
+ }
+
/** Below are private helper methods */
private void addView(View view) {
diff --git a/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java b/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java
index 42b40c4..a47c354 100644
--- a/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java
+++ b/autofill/autofill/src/main/java/androidx/autofill/inline/common/ViewStyle.java
@@ -80,7 +80,11 @@
if (mBundle.containsKey(KEY_PADDING)) {
int[] padding = mBundle.getIntArray(KEY_PADDING);
if (padding != null && padding.length == 4) {
- view.setPadding(padding[0], padding[1], padding[2], padding[3]);
+ if (view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+ view.setPadding(padding[0], padding[1], padding[2], padding[3]);
+ } else {
+ view.setPadding(padding[2], padding[1], padding[0], padding[3]);
+ }
}
}
if (mBundle.containsKey(KEY_LAYOUT_MARGIN)) {
@@ -94,9 +98,16 @@
} else if (!(layoutParams instanceof ViewGroup.MarginLayoutParams)) {
layoutParams = new ViewGroup.MarginLayoutParams(layoutParams);
}
- ((ViewGroup.MarginLayoutParams) layoutParams).setMargins(layoutMargin[0],
- layoutMargin[1], layoutMargin[2], layoutMargin[3]);
- view.setLayoutParams(layoutParams);
+ ViewGroup.MarginLayoutParams marginLayoutParams =
+ (ViewGroup.MarginLayoutParams) layoutParams;
+ if (view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
+ marginLayoutParams.setMargins(layoutMargin[0],
+ layoutMargin[1], layoutMargin[2], layoutMargin[3]);
+ } else {
+ marginLayoutParams.setMargins(layoutMargin[2],
+ layoutMargin[1], layoutMargin[0], layoutMargin[3]);
+ }
+ view.setLayoutParams(marginLayoutParams);
}
}
}
@@ -163,32 +174,38 @@
/**
* Sets the padding.
*
- * @param left the left padding in pixels
+ * <p> Note that the method takes start/end rather than left/right, respecting the layout
+ * direction.
+ *
+ * @param start the start padding in pixels
* @param top the top padding in pixels
- * @param right the right padding in pixels
+ * @param end the end padding in pixels
* @param bottom the bottom padding in pixels
* @see android.view.View#setPadding(int, int, int, int)
*/
@NonNull
- public B setPadding(int left, int top, int right, int bottom) {
- mBundle.putIntArray(KEY_PADDING, new int[]{left, top, right, bottom});
+ public B setPadding(int start, int top, int end, int bottom) {
+ mBundle.putIntArray(KEY_PADDING, new int[]{start, top, end, bottom});
return getThis();
}
/**
* Sets the layout margin through the view's layout param.
*
- * @param left the left margin size
+ * <p> Note that the method takes start/end rather than left/right, respecting the layout
+ * direction.
+ *
+ * @param start the start margin size
* @param top the top margin size
- * @param right the right margin size
+ * @param end the end margin size
* @param bottom the bottom margin size
* @see android.view.ViewGroup.MarginLayoutParams#setMargins(int, int, int, int)
* @see android.view.View#setLayoutParams(android.view.ViewGroup.LayoutParams)
*/
@NonNull
- public B setLayoutMargin(int left, int top, int right,
+ public B setLayoutMargin(int start, int top, int end,
int bottom) {
- mBundle.putIntArray(KEY_LAYOUT_MARGIN, new int[]{left, top, right, bottom});
+ mBundle.putIntArray(KEY_LAYOUT_MARGIN, new int[]{start, top, end, bottom});
return getThis();
}
}
diff --git a/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java b/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java
index 0d2965a..6d4adc9 100644
--- a/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java
+++ b/autofill/autofill/src/main/java/androidx/autofill/inline/v1/InlineSuggestionUi.java
@@ -210,6 +210,7 @@
private static final String KEY_END_ICON_STYLE = "end_icon_style";
private static final String KEY_SINGLE_ICON_CHIP_STYLE = "single_icon_chip_style";
private static final String KEY_SINGLE_ICON_CHIP_ICON_STYLE = "single_icon_chip_icon_style";
+ private static final String KEY_LAYOUT_DIRECTION = "layout_direction";
/**
* Use {@link InlineSuggestionUi#fromBundle(Bundle)} or {@link Builder#build()} to
@@ -238,6 +239,10 @@
if (!isValid()) {
return;
}
+
+ // layout direction
+ singleIconChipView.setLayoutDirection(getLayoutDirection());
+
// single icon
if (singleIconView.getVisibility() != View.GONE) {
ImageViewStyle singleIconViewStyle = getSingleIconChipIconStyle();
@@ -268,6 +273,10 @@
if (!isValid()) {
return;
}
+
+ // layout direction
+ chipView.setLayoutDirection(getLayoutDirection());
+
// start icon
if (startIconView.getVisibility() != View.GONE) {
ImageViewStyle startIconViewStyle = getStartIconStyle();
@@ -313,6 +322,17 @@
return UiVersions.INLINE_UI_VERSION_1;
}
+ /**
+ * @see Builder#setLayoutDirection(int)
+ */
+ public int getLayoutDirection() {
+ int layoutDirection = mBundle.getInt(KEY_LAYOUT_DIRECTION, View.LAYOUT_DIRECTION_LTR);
+ if (layoutDirection != View.LAYOUT_DIRECTION_LTR
+ && layoutDirection != View.LAYOUT_DIRECTION_RTL) {
+ layoutDirection = View.LAYOUT_DIRECTION_LTR;
+ }
+ return layoutDirection;
+ }
/**
* @see Builder#setChipStyle(ViewStyle)
@@ -390,6 +410,24 @@
}
/**
+ * Sets the layout direction for the UI.
+ *
+ * <p>Note that the process that renders the UI needs to have
+ * {@code android:supportsRtl="true"} for this to take effect.
+ *
+ * @param layoutDirection the layout direction to set. Should be one of:
+ * {@link View#LAYOUT_DIRECTION_LTR},
+ * {@link View#LAYOUT_DIRECTION_RTL}.
+ *
+ * @see View#setLayoutDirection(int)
+ */
+ @NonNull
+ public Builder setLayoutDirection(int layoutDirection) {
+ mBundle.putInt(KEY_LAYOUT_DIRECTION, layoutDirection);
+ return this;
+ }
+
+ /**
* Sets the chip style.
*
* <p>See {@link #setSingleIconChipStyle(ViewStyle)} for more information about setting
diff --git a/autofill/autofill/src/main/res/values/dimens.xml b/autofill/autofill/src/main/res/values/dimens.xml
index 257c7ed..2cbe67a 100644
--- a/autofill/autofill/src/main/res/values/dimens.xml
+++ b/autofill/autofill/src/main/res/values/dimens.xml
@@ -17,5 +17,4 @@
<resources>
<dimen name="autofill_inline_suggestion_icon_size">20dp</dimen>
- <dimen name="autofill_inline_suggestion_single_icon_size">24dp</dimen>
</resources>
diff --git a/autofill/autofill/src/main/res/values/styles.xml b/autofill/autofill/src/main/res/values/styles.xml
index f0601bd..a986979 100644
--- a/autofill/autofill/src/main/res/values/styles.xml
+++ b/autofill/autofill/src/main/res/values/styles.xml
@@ -21,7 +21,9 @@
<style name="Widget.Autofill.InlineSuggestionChip">
<item name="android:background">@drawable/autofill_inline_suggestion_chip_background</item>
+ <item name="android:paddingStart">13dp</item>
<item name="android:paddingLeft">13dp</item>
+ <item name="android:paddingEnd">13dp</item>
<item name="android:paddingRight">13dp</item>
</style>
@@ -35,7 +37,9 @@
<item name="android:textColor">#FF202124</item>
<item name="android:textSize">16sp</item>
<item name="android:typeface">sans</item>
+ <item name="android:layout_marginStart">4dp</item>
<item name="android:layout_marginLeft">4dp</item>
+ <item name="android:layout_marginEnd">4dp</item>
<item name="android:layout_marginRight">4dp</item>
</style>
@@ -43,6 +47,7 @@
<item name="android:textColor">#99202124</item>
<item name="android:textSize">14sp</item>
<item name="android:typeface">sans</item>
+ <item name="android:layout_marginEnd">4dp</item>
<item name="android:layout_marginRight">4dp</item>
</style>
diff --git a/benchmark/benchmark/src/androidTest/AndroidManifest.xml b/benchmark/benchmark/src/androidTest/AndroidManifest.xml
index 82470db..b20d8c1 100644
--- a/benchmark/benchmark/src/androidTest/AndroidManifest.xml
+++ b/benchmark/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/benchmark/common/api/1.1.0-alpha01.txt b/benchmark/common/api/1.1.0-alpha01.txt
index 291b7b8..4f7ae83 100644
--- a/benchmark/common/api/1.1.0-alpha01.txt
+++ b/benchmark/common/api/1.1.0-alpha01.txt
@@ -8,7 +8,7 @@
method public boolean keepRunning();
method public void pauseTiming();
method public void resumeTiming();
- field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
}
public static final class BenchmarkState.Companion {
diff --git a/benchmark/common/api/1.1.0-alpha02.ignore b/benchmark/common/api/1.1.0-alpha02.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/1.1.0-alpha02.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+ Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/1.1.0-alpha02.txt b/benchmark/common/api/1.1.0-alpha02.txt
new file mode 100644
index 0000000..8e0fdce
--- /dev/null
+++ b/benchmark/common/api/1.1.0-alpha02.txt
@@ -0,0 +1,21 @@
+// Signature format: 3.0
+package androidx.benchmark {
+
+ public final class ArgumentsKt {
+ }
+
+ public final class BenchmarkState {
+ method public boolean keepRunning();
+ method public void pauseTiming();
+ method public void resumeTiming();
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+ }
+
+ public static final class BenchmarkState.Companion {
+ }
+
+ public final class MetricNameUtilsKt {
+ }
+
+}
+
diff --git a/benchmark/common/api/current.txt b/benchmark/common/api/current.txt
index 291b7b8..8e0fdce 100644
--- a/benchmark/common/api/current.txt
+++ b/benchmark/common/api/current.txt
@@ -8,15 +8,12 @@
method public boolean keepRunning();
method public void pauseTiming();
method public void resumeTiming();
- field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
}
public static final class BenchmarkState.Companion {
}
- public final class IdeOutputKt {
- }
-
public final class MetricNameUtilsKt {
}
diff --git a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
index 4aaaeed..80824a4 100644
--- a/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
+++ b/benchmark/common/api/public_plus_experimental_1.1.0-alpha01.txt
@@ -11,7 +11,7 @@
method public void pauseTiming();
method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
method public void resumeTiming();
- field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
}
public static final class BenchmarkState.Companion {
diff --git a/benchmark/common/api/public_plus_experimental_1.1.0-alpha02.txt b/benchmark/common/api/public_plus_experimental_1.1.0-alpha02.txt
new file mode 100644
index 0000000..fc72f89
--- /dev/null
+++ b/benchmark/common/api/public_plus_experimental_1.1.0-alpha02.txt
@@ -0,0 +1,28 @@
+// Signature format: 3.0
+package androidx.benchmark {
+
+ public final class ArgumentsKt {
+ }
+
+ public final class BenchmarkState {
+ ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public BenchmarkState();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public long getMinTimeNanos();
+ method public boolean keepRunning();
+ method public void pauseTiming();
+ method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
+ method public void resumeTiming();
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+ }
+
+ public static final class BenchmarkState.Companion {
+ method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
+ }
+
+ @kotlin.Experimental @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
+ }
+
+ public final class MetricNameUtilsKt {
+ }
+
+}
+
diff --git a/benchmark/common/api/public_plus_experimental_current.txt b/benchmark/common/api/public_plus_experimental_current.txt
index 4aaaeed..fc72f89 100644
--- a/benchmark/common/api/public_plus_experimental_current.txt
+++ b/benchmark/common/api/public_plus_experimental_current.txt
@@ -11,7 +11,7 @@
method public void pauseTiming();
method @androidx.benchmark.BenchmarkState.Companion.ExperimentalExternalReport public static void reportData(String className, String testName, @IntRange(from=0) long totalRunTimeNs, java.util.List<java.lang.Long> dataNs, @IntRange(from=0) int warmupIterations, @IntRange(from=0) long thermalThrottleSleepSeconds, @IntRange(from=1) int repeatIterations);
method public void resumeTiming();
- field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
}
public static final class BenchmarkState.Companion {
@@ -21,9 +21,6 @@
@kotlin.Experimental @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public static @interface BenchmarkState.Companion.ExperimentalExternalReport {
}
- public final class IdeOutputKt {
- }
-
public final class MetricNameUtilsKt {
}
diff --git a/benchmark/common/api/res-1.1.0-alpha02.txt b/benchmark/common/api/res-1.1.0-alpha02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/common/api/res-1.1.0-alpha02.txt
diff --git a/benchmark/common/api/restricted_1.1.0-alpha01.txt b/benchmark/common/api/restricted_1.1.0-alpha01.txt
index a91c3dc..c39c72d3 100644
--- a/benchmark/common/api/restricted_1.1.0-alpha01.txt
+++ b/benchmark/common/api/restricted_1.1.0-alpha01.txt
@@ -9,7 +9,7 @@
method @kotlin.PublishedApi internal boolean keepRunningInternal();
method public void pauseTiming();
method public void resumeTiming();
- field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
field @kotlin.PublishedApi internal int iterationsRemaining;
}
diff --git a/benchmark/common/api/restricted_1.1.0-alpha02.ignore b/benchmark/common/api/restricted_1.1.0-alpha02.ignore
new file mode 100644
index 0000000..44a73f7
--- /dev/null
+++ b/benchmark/common/api/restricted_1.1.0-alpha02.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedClass: androidx.benchmark.TraceCompatKt:
+ Removed class androidx.benchmark.TraceCompatKt
diff --git a/benchmark/common/api/restricted_1.1.0-alpha02.txt b/benchmark/common/api/restricted_1.1.0-alpha02.txt
new file mode 100644
index 0000000..5c18529
--- /dev/null
+++ b/benchmark/common/api/restricted_1.1.0-alpha02.txt
@@ -0,0 +1,23 @@
+// Signature format: 3.0
+package androidx.benchmark {
+
+ public final class ArgumentsKt {
+ }
+
+ public final class BenchmarkState {
+ method public boolean keepRunning();
+ method @kotlin.PublishedApi internal boolean keepRunningInternal();
+ method public void pauseTiming();
+ method public void resumeTiming();
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
+ field @kotlin.PublishedApi internal int iterationsRemaining;
+ }
+
+ public static final class BenchmarkState.Companion {
+ }
+
+ public final class MetricNameUtilsKt {
+ }
+
+}
+
diff --git a/benchmark/common/api/restricted_current.txt b/benchmark/common/api/restricted_current.txt
index a91c3dc..5c18529 100644
--- a/benchmark/common/api/restricted_current.txt
+++ b/benchmark/common/api/restricted_current.txt
@@ -9,16 +9,13 @@
method @kotlin.PublishedApi internal boolean keepRunningInternal();
method public void pauseTiming();
method public void resumeTiming();
- field public static final androidx.benchmark.BenchmarkState.Companion! Companion;
+ field public static final androidx.benchmark.BenchmarkState.Companion Companion;
field @kotlin.PublishedApi internal int iterationsRemaining;
}
public static final class BenchmarkState.Companion {
}
- public final class IdeOutputKt {
- }
-
public final class MetricNameUtilsKt {
}
diff --git a/benchmark/common/src/androidTest/java/androidx/benchmark/IdeOutputTest.kt b/benchmark/common/src/androidTest/java/androidx/benchmark/InstrumentationResultsTest.kt
similarity index 78%
rename from benchmark/common/src/androidTest/java/androidx/benchmark/IdeOutputTest.kt
rename to benchmark/common/src/androidTest/java/androidx/benchmark/InstrumentationResultsTest.kt
index e0209ad..a435e31 100644
--- a/benchmark/common/src/androidTest/java/androidx/benchmark/IdeOutputTest.kt
+++ b/benchmark/common/src/androidTest/java/androidx/benchmark/InstrumentationResultsTest.kt
@@ -24,11 +24,11 @@
@SmallTest
@RunWith(JUnit4::class)
-class IdeOutputTest {
+class InstrumentationResultsTest {
@Test
fun ideSummary_alignment() {
- val summary1 = ideSummaryLine("foo", 1000, 100)
- val summary2 = ideSummaryLine("fooBarLongerKey", 10000, 0)
+ val summary1 = InstrumentationResults.ideSummaryLine("foo", 1000, 100)
+ val summary2 = InstrumentationResults.ideSummaryLine("fooBarLongerKey", 10000, 0)
assertEquals(
summary1.indexOf("foo"),
@@ -40,11 +40,11 @@
fun ideSummary_allocs() {
assertEquals(
" 1,000 ns foo",
- ideSummaryLine("foo", 1000, null)
+ InstrumentationResults.ideSummaryLine("foo", 1000, null)
)
assertEquals(
" 1,000 ns 10 allocs foo",
- ideSummaryLine("foo", 1000, 10)
+ InstrumentationResults.ideSummaryLine("foo", 1000, 10)
)
}
}
\ No newline at end of file
diff --git a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
index c1abfdf..d308221 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/BenchmarkState.kt
@@ -25,7 +25,6 @@
import androidx.annotation.RestrictTo
import androidx.annotation.VisibleForTesting
import androidx.benchmark.Errors.PREFIX
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.tracing.Trace
import java.io.File
import java.util.concurrent.TimeUnit
@@ -217,6 +216,7 @@
).absolutePath
Log.d(TAG, "Profiling output file: $path")
+ InstrumentationResults.reportAdditionalFileToCopy("profiling_trace", path)
val bufferSize = 16 * 1024 * 1024
if (Arguments.profilingMode == ProfilingMode.Sampled &&
@@ -528,10 +528,12 @@
// these 'legacy' CI output stats are considered output
stats.forEach { it.putInBundle(status, PREFIX) }
}
- status.putIdeSummaryLine(
- testName = key,
- nanos = getMinTimeNanos(),
- allocations = stats.firstOrNull { it.name == "allocationCount" }?.median
+ status.putAll(
+ InstrumentationResults.getIdeSummaryLine(
+ testName = key,
+ nanos = getMinTimeNanos(),
+ allocations = stats.firstOrNull { it.name == "allocationCount" }?.median
+ )
)
return status
}
@@ -560,8 +562,9 @@
checkState() // this method is triggered externally
val fullTestName = "$PREFIX$simpleClassName.$methodName"
- val bundle = getFullStatusReport(key = fullTestName, includeStats = !Arguments.dryRunMode)
- reportBundle(bundle)
+ InstrumentationResults.report(
+ getFullStatusReport(key = fullTestName, includeStats = !Arguments.dryRunMode)
+ )
ResultWriter.appendReport(
getReport(
@@ -659,30 +662,18 @@
warmupIterations = warmupIterations
)
// Report value to Studio console
- val bundle = Bundle()
val fullTestName = PREFIX +
if (className.isNotEmpty()) "$className.$testName" else testName
- bundle.putIdeSummaryLine(
- testName = fullTestName,
- nanos = report.getStats("timeNs").min,
- allocations = null
+ InstrumentationResults.report(
+ InstrumentationResults.getIdeSummaryLine(
+ testName = fullTestName,
+ nanos = report.getStats("timeNs").min,
+ allocations = null
+ )
)
- reportBundle(bundle)
// Report values to file output
ResultWriter.appendReport(report)
}
-
- /**
- * Report results bundle to instrumentation
- *
- * Before addResults() was added in the platform, we use sendStatus(). The constant '2'
- * comes from IInstrumentationResultParser.StatusCodes.IN_PROGRESS, and signals the
- * test infra that this is an "additional result" bundle, equivalent to addResults()
- * NOTE: we should a version check to call addResults(), but don't yet due to b/155103514
- */
- internal fun reportBundle(
- bundle: Bundle
- ) = InstrumentationRegistry.getInstrumentation().sendStatus(2, bundle)
}
}
diff --git a/benchmark/common/src/main/java/androidx/benchmark/IdeOutput.kt b/benchmark/common/src/main/java/androidx/benchmark/IdeOutput.kt
deleted file mode 100644
index 7146f5b..0000000
--- a/benchmark/common/src/main/java/androidx/benchmark/IdeOutput.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.benchmark
-
-import android.os.Bundle
-import java.text.NumberFormat
-
-private const val STUDIO_OUTPUT_KEY_PREFIX = "android.studio.display."
-private const val STUDIO_OUTPUT_KEY_ID = "benchmark"
-
-private fun ideSummaryLineWrapped(key: String, nanos: Long, allocations: Long?): String {
- val warningLines =
- Errors.acquireWarningStringForLogging()?.split("\n") ?: listOf()
- return (warningLines + ideSummaryLine(key, nanos, allocations))
- // remove first line if empty
- .filterIndexed { index, it -> index != 0 || it.isNotEmpty() }
- // join, prepending key to everything but first string,
- // to make each line look the same
- .joinToString("\n$STUDIO_OUTPUT_KEY_ID: ")
-}
-
-// NOTE: this summary line will use default locale to determine separators. As
-// this line is only meant for human eyes, we don't worry about consistency here.
-internal fun ideSummaryLine(key: String, nanos: Long, allocations: Long?): String {
- val numberFormat = NumberFormat.getNumberInstance()
- return listOfNotNull(
- // 13 alignment is enough for ~10 seconds
- "%13s ns".format(numberFormat.format(nanos)),
- // 9 alignment is enough for ~10 million allocations
- allocations?.run {
- "%8s allocs".format(numberFormat.format(allocations))
- },
- key
- ).joinToString(" ")
-}
-
-internal fun Bundle.putIdeSummaryLine(testName: String, nanos: Long, allocations: Long?) {
- putString(
- STUDIO_OUTPUT_KEY_PREFIX + STUDIO_OUTPUT_KEY_ID,
- ideSummaryLineWrapped(testName, nanos, allocations)
- )
-}
\ No newline at end of file
diff --git a/benchmark/common/src/main/java/androidx/benchmark/InstrumentationResults.kt b/benchmark/common/src/main/java/androidx/benchmark/InstrumentationResults.kt
new file mode 100644
index 0000000..436735a
--- /dev/null
+++ b/benchmark/common/src/main/java/androidx/benchmark/InstrumentationResults.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark
+
+import android.os.Bundle
+import androidx.test.platform.app.InstrumentationRegistry
+import java.text.NumberFormat
+
+/**
+ * Provides way to report additional results via `Instrumentation.sendStatus()` / `addResult()`.
+ */
+internal object InstrumentationResults {
+ private const val STUDIO_OUTPUT_KEY_PREFIX = "android.studio.display."
+ private const val STUDIO_OUTPUT_KEY_ID = "benchmark"
+
+ private const val ADDITIONAL_FILE_OUTPUT_KEY_PREFIX = "additionalTestOutputFile_"
+
+ private fun ideSummaryLineWrapped(key: String, nanos: Long, allocations: Long?): String {
+ val warningLines =
+ Errors.acquireWarningStringForLogging()?.split("\n") ?: listOf()
+ return (warningLines + ideSummaryLine(key, nanos, allocations))
+ // remove first line if empty
+ .filterIndexed { index, it -> index != 0 || it.isNotBlank() }
+ // join, prepending key to everything but first string,
+ // to make each line look the same
+ .joinToString("\n$STUDIO_OUTPUT_KEY_ID: ")
+ }
+
+ // NOTE: this summary line will use default locale to determine separators. As
+ // this line is only meant for human eyes, we don't worry about consistency here.
+ internal fun ideSummaryLine(key: String, nanos: Long, allocations: Long?): String {
+ val numberFormat = NumberFormat.getNumberInstance()
+ return listOfNotNull(
+ // 13 alignment is enough for ~10 seconds
+ "%13s ns".format(numberFormat.format(nanos)),
+ // 9 alignment is enough for ~10 million allocations
+ allocations?.run {
+ "%8s allocs".format(numberFormat.format(allocations))
+ },
+ key
+ ).joinToString(" ")
+ }
+
+ internal fun getIdeSummaryLine(testName: String, nanos: Long, allocations: Long?) =
+ Bundle().also {
+ it.putString(
+ STUDIO_OUTPUT_KEY_PREFIX + STUDIO_OUTPUT_KEY_ID,
+ ideSummaryLineWrapped(testName, nanos, allocations)
+ )
+ }
+
+ internal fun reportAdditionalFileToCopy(key: String, absoluteFilePath: String) {
+ reportBundle(Bundle().also {
+ it.putString(ADDITIONAL_FILE_OUTPUT_KEY_PREFIX + key, absoluteFilePath)
+ })
+ }
+
+ internal fun report(bundle: Bundle) {
+ reportBundle(bundle)
+ }
+
+ /**
+ * Report results bundle to instrumentation
+ *
+ * Before addResults() was added in the platform, we use sendStatus(). The constant '2'
+ * comes from IInstrumentationResultParser.StatusCodes.IN_PROGRESS, and signals the
+ * test infra that this is an "additional result" bundle, equivalent to addResults()
+ * NOTE: we should a version check to call addResults(), but don't yet due to b/155103514
+ */
+ private fun reportBundle(bundle: Bundle) {
+ InstrumentationRegistry
+ .getInstrumentation()
+ .sendStatus(2, bundle)
+ }
+}
\ No newline at end of file
diff --git a/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt b/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt
index c61d8f9..7505146 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/ResultWriter.kt
@@ -38,6 +38,7 @@
val file = File(Arguments.testOutputDir, "$packageName-benchmarkData.json")
writeReport(file, reports)
+ InstrumentationResults.reportAdditionalFileToCopy("results_json", file.absolutePath)
}
}
diff --git a/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml b/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml
index 6434fda..3362f60 100644
--- a/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml
+++ b/benchmark/integration-tests/startup-benchmark/src/androidTest/AndroidManifest.xml
@@ -19,9 +19,12 @@
xmlns:tools="http://schemas.android.com/tools"
package="androidx.benchmark.integration.startup.benchmark.test">
<application
- android:name="androidx.benchmark.integration.startup.benchmark.ArgumentInjectingApplication"
- android:debuggable="false"
- tools:ignore="HardcodedDebugMode"
- tools:replace="android:debuggable" />
- />
+ android:name="androidx.benchmark.integration.startup.benchmark.ArgumentInjectingApplication"
+ android:debuggable="false"
+ tools:ignore="HardcodedDebugMode"
+ tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable shell="true"/>
+ </application>
</manifest>
diff --git a/benchmark/junit4/api/1.1.0-alpha02.txt b/benchmark/junit4/api/1.1.0-alpha02.txt
new file mode 100644
index 0000000..34ad6a658
--- /dev/null
+++ b/benchmark/junit4/api/1.1.0-alpha02.txt
@@ -0,0 +1,23 @@
+// Signature format: 3.0
+package androidx.benchmark.junit4 {
+
+ public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+ ctor public AndroidBenchmarkRunner();
+ }
+
+ public final class BenchmarkRule implements org.junit.rules.TestRule {
+ ctor public BenchmarkRule();
+ method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+ method public androidx.benchmark.BenchmarkState getState();
+ }
+
+ public final class BenchmarkRule.Scope {
+ method public inline <T> T! runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
+ public final class BenchmarkRuleKt {
+ method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+ }
+
+}
+
diff --git a/benchmark/junit4/api/public_plus_experimental_1.1.0-alpha02.txt b/benchmark/junit4/api/public_plus_experimental_1.1.0-alpha02.txt
new file mode 100644
index 0000000..34ad6a658
--- /dev/null
+++ b/benchmark/junit4/api/public_plus_experimental_1.1.0-alpha02.txt
@@ -0,0 +1,23 @@
+// Signature format: 3.0
+package androidx.benchmark.junit4 {
+
+ public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+ ctor public AndroidBenchmarkRunner();
+ }
+
+ public final class BenchmarkRule implements org.junit.rules.TestRule {
+ ctor public BenchmarkRule();
+ method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+ method public androidx.benchmark.BenchmarkState getState();
+ }
+
+ public final class BenchmarkRule.Scope {
+ method public inline <T> T! runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
+ public final class BenchmarkRuleKt {
+ method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+ }
+
+}
+
diff --git a/benchmark/junit4/api/res-1.1.0-alpha02.txt b/benchmark/junit4/api/res-1.1.0-alpha02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/benchmark/junit4/api/res-1.1.0-alpha02.txt
diff --git a/benchmark/junit4/api/restricted_1.1.0-alpha02.txt b/benchmark/junit4/api/restricted_1.1.0-alpha02.txt
new file mode 100644
index 0000000..ac47d85
--- /dev/null
+++ b/benchmark/junit4/api/restricted_1.1.0-alpha02.txt
@@ -0,0 +1,24 @@
+// Signature format: 3.0
+package androidx.benchmark.junit4 {
+
+ public class AndroidBenchmarkRunner extends androidx.test.runner.AndroidJUnitRunner {
+ ctor public AndroidBenchmarkRunner();
+ }
+
+ public final class BenchmarkRule implements org.junit.rules.TestRule {
+ ctor public BenchmarkRule();
+ method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+ method public androidx.benchmark.BenchmarkState getState();
+ }
+
+ public final class BenchmarkRule.Scope {
+ method @kotlin.PublishedApi internal androidx.benchmark.BenchmarkState getOuterState();
+ method public inline <T> T! runWithTimingDisabled(kotlin.jvm.functions.Function0<? extends T> block);
+ }
+
+ public final class BenchmarkRuleKt {
+ method public static inline void measureRepeated(androidx.benchmark.junit4.BenchmarkRule, kotlin.jvm.functions.Function1<? super androidx.benchmark.junit4.BenchmarkRule.Scope,kotlin.Unit> block);
+ }
+
+}
+
diff --git a/browser/browser/api/api_lint.ignore b/browser/browser/api/api_lint.ignore
index a4d5f5e..0a088b5 100644
--- a/browser/browser/api/api_lint.ignore
+++ b/browser/browser/api/api_lint.ignore
@@ -57,8 +57,6 @@
Must avoid boxed primitives (`java.lang.Integer`)
-BuilderSetStyle: androidx.browser.customtabs.CustomTabsIntent.Builder#enableUrlBarHiding():
- Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.browser.customtabs.CustomTabsIntent.Builder.enableUrlBarHiding()
BuilderSetStyle: androidx.browser.trusted.TrustedWebActivityIntentBuilder#buildCustomTabsIntent():
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.browser.trusted.TrustedWebActivityIntentBuilder.buildCustomTabsIntent()
@@ -79,7 +77,7 @@
Listeners should always be at end of argument list (method `newSession`)
-OptionalBuilderConstructorAgrument: androidx.browser.customtabs.CustomTabsIntent.Builder#Builder(androidx.browser.customtabs.CustomTabsSession) parameter #0:
+OptionalBuilderConstructorArgument: androidx.browser.customtabs.CustomTabsIntent.Builder#Builder(androidx.browser.customtabs.CustomTabsSession) parameter #0:
Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter session in androidx.browser.customtabs.CustomTabsIntent.Builder(androidx.browser.customtabs.CustomTabsSession session)
diff --git a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
index b0e39b7..c415c6b 100644
--- a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
@@ -136,6 +136,7 @@
"-Xep:ParameterName:ERROR",
"-Xep:RxReturnValueIgnored:ERROR",
"-Xep:BadImport:ERROR",
+ "-Xep:MissingCasesInEnumSwitch:ERROR",
// Nullaway
"-XepIgnoreUnknownCheckNames", // https://github.com/uber/NullAway/issues/25
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 59fd81d..34252fe 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -31,7 +31,7 @@
val ARCH_RUNTIME = Version("2.2.0-alpha01")
val ASYNCLAYOUTINFLATER = Version("1.1.0-alpha01")
val AUTOFILL = Version("1.1.0-alpha02")
- val BENCHMARK = Version("1.1.0-alpha01")
+ val BENCHMARK = Version("1.1.0-alpha02")
val BIOMETRIC = Version("1.1.0-alpha01")
val BROWSER = Version("1.3.0-alpha04")
val BUILDSRC_TESTS = Version("1.0.0-alpha01")
@@ -79,7 +79,7 @@
val MEDIA2 = Version("1.1.0-alpha01")
val MEDIAROUTER = Version("1.2.0-alpha01")
val NAVIGATION = Version("2.4.0-alpha01")
- val PAGING = Version("3.0.0-alpha02")
+ val PAGING = Version("3.0.0-alpha03")
val PALETTE = Version("1.1.0-alpha01")
val PRINT = Version("1.1.0-alpha01")
val PERCENTLAYOUT = Version("1.1.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
index a866f37..e2e55fd 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -153,7 +153,12 @@
isAbortOnError = false
// Avoid printing every single lint error to the terminal
textReport = false
- lintBaseline.delete()
+ val lintDebugTask = tasks.named("lintDebug")
+ lintDebugTask.configure {
+ it.doFirst {
+ lintBaseline.delete()
+ }
+ }
System.setProperty(LINT_BASELINE_CONTINUE, "true")
}
baseline(lintBaseline)
diff --git a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
index 5fed039..65197d9 100644
--- a/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/PublishDocsRules.kt
@@ -41,20 +41,20 @@
prebuilts(LibraryGroups.AUTOFILL, "1.1.0-alpha01")
ignore(LibraryGroups.BENCHMARK.group, "benchmark-gradle-plugin")
prebuilts(LibraryGroups.BENCHMARK, "1.1.0-alpha01")
- prebuilts(LibraryGroups.BIOMETRIC, "biometric", "1.0.1")
- prebuilts(LibraryGroups.BROWSER, "1.3.0-alpha03")
+ prebuilts(LibraryGroups.BIOMETRIC, "biometric", "1.1.0-alpha01")
+ prebuilts(LibraryGroups.BROWSER, "1.3.0-alpha04")
ignore(LibraryGroups.CAMERA.group, "camera-camera2-pipe")
ignore(LibraryGroups.CAMERA.group, "camera-camera2-pipe-integration")
ignore(LibraryGroups.CAMERA.group, "camera-testing")
ignore(LibraryGroups.CAMERA.group, "camera-extensions-stub")
ignore(LibraryGroups.CAMERA.group, "camera-testlib-extensions")
- prebuilts(LibraryGroups.CAMERA, "camera-view", "1.0.0-alpha12")
- prebuilts(LibraryGroups.CAMERA, "camera-extensions", "1.0.0-alpha12")
+ prebuilts(LibraryGroups.CAMERA, "camera-view", "1.0.0-alpha13")
+ prebuilts(LibraryGroups.CAMERA, "camera-extensions", "1.0.0-alpha13")
.addStubs("camera/camera-extensions-stub/camera-extensions-stub.jar")
- prebuilts(LibraryGroups.CAMERA, "1.0.0-beta05")
+ prebuilts(LibraryGroups.CAMERA, "1.0.0-beta06")
prebuilts(LibraryGroups.CARDVIEW, "1.0.0")
prebuilts(LibraryGroups.COLLECTION, "1.1.0")
- prebuilts(LibraryGroups.CONCURRENT, "1.1.0-alpha01")
+ prebuilts(LibraryGroups.CONCURRENT, "1.1.0-beta01")
prebuilts(LibraryGroups.CONTENTPAGER, "1.0.0")
prebuilts(LibraryGroups.COORDINATORLAYOUT, "1.1.0")
prebuilts(LibraryGroups.CORE, "core", "1.5.0-alpha01")
@@ -68,7 +68,7 @@
prebuilts(LibraryGroups.DRAWERLAYOUT, "1.1.0")
prebuilts(LibraryGroups.DYNAMICANIMATION, "dynamicanimation-ktx", "1.0.0-alpha03")
prebuilts(LibraryGroups.DYNAMICANIMATION, "1.1.0-alpha02")
- prebuilts(LibraryGroups.EMOJI, "1.1.0-rc01")
+ prebuilts(LibraryGroups.EMOJI, "1.1.0")
prebuilts(LibraryGroups.ENTERPRISE, "1.0.0")
prebuilts(LibraryGroups.EXIFINTERFACE, "1.3.0-alpha01")
ignore(LibraryGroups.FRAGMENT.group, "fragment-lint")
@@ -87,21 +87,21 @@
ignore(LibraryGroups.LIFECYCLE.group, "lifecycle-runtime-ktx-lint")
prebuilts(LibraryGroups.LIFECYCLE, "lifecycle-extensions", "2.2.0") // No longer published
ignore(LibraryGroups.LIFECYCLE.group, "lifecycle-runtime-testing")
- prebuilts(LibraryGroups.LIFECYCLE, "2.3.0-alpha04")
+ prebuilts(LibraryGroups.LIFECYCLE, "2.3.0-alpha05")
ignore(LibraryGroups.LOADER.group, "loader-ktx")
prebuilts(LibraryGroups.LOADER, "1.1.0")
prebuilts(LibraryGroups.LOCALBROADCASTMANAGER, "1.1.0-alpha01")
- prebuilts(LibraryGroups.MEDIA, "media", "1.2.0-alpha03")
+ prebuilts(LibraryGroups.MEDIA, "media", "1.2.0-alpha04")
ignore(LibraryGroups.MEDIA2.group, "media2-exoplayer")
- prebuilts(LibraryGroups.MEDIA2, "media2-widget", "1.0.3")
- prebuilts(LibraryGroups.MEDIA2, "1.0.3")
+ prebuilts(LibraryGroups.MEDIA2, "media2-widget", "1.1.0-alpha01")
+ prebuilts(LibraryGroups.MEDIA2, "1.1.0-alpha01")
prebuilts(LibraryGroups.MEDIAROUTER, "1.2.0-alpha01")
ignore(LibraryGroups.NAVIGATION.group, "navigation-runtime-truth")
ignore(LibraryGroups.NAVIGATION.group, "navigation-safe-args-generator")
ignore(LibraryGroups.NAVIGATION.group, "navigation-safe-args-gradle-plugin")
- prebuilts(LibraryGroups.NAVIGATION, "2.3.0-rc01")
+ prebuilts(LibraryGroups.NAVIGATION, "2.3.0")
ignore(LibraryGroups.PAGING.group, "paging-guava")
- prebuilts(LibraryGroups.PAGING, "3.0.0-alpha01")
+ prebuilts(LibraryGroups.PAGING, "3.0.0-alpha02")
prebuilts(LibraryGroups.PALETTE, "1.0.0")
// 1.0.1 was created to fix reference docs. It contains no actual source changes from 1.0.0
prebuilts(LibraryGroups.PERCENTLAYOUT, "1.0.1")
@@ -109,7 +109,7 @@
prebuilts(LibraryGroups.PREFERENCE, "1.1.1")
prebuilts(LibraryGroups.PRINT, "1.0.0")
prebuilts(LibraryGroups.RECOMMENDATION, "1.0.0")
- prebuilts(LibraryGroups.RECYCLERVIEW, "recyclerview", "1.2.0-alpha03")
+ prebuilts(LibraryGroups.RECYCLERVIEW, "recyclerview", "1.2.0-alpha04")
prebuilts(LibraryGroups.RECYCLERVIEW, "recyclerview-selection", "2.0.0-alpha01")
ignore(LibraryGroups.RECYCLERVIEW.group, "recyclerview-lint")
prebuilts(LibraryGroups.REMOTECALLBACK, "1.0.0-alpha02")
@@ -136,11 +136,11 @@
ignore(LibraryGroups.INSPECTION_EXTENSIONS.group, "sqlite-inspection")
prebuilts(LibraryGroups.SQLITE, "2.1.0")
prebuilts(LibraryGroups.STARTUP, "1.0.0-alpha01")
- prebuilts(LibraryGroups.SWIPEREFRESHLAYOUT, "1.1.0-rc01")
+ prebuilts(LibraryGroups.SWIPEREFRESHLAYOUT, "1.1.0")
prebuilts(LibraryGroups.TEXTCLASSIFIER, "1.0.0-alpha03")
- prebuilts(LibraryGroups.TRACING, "1.0.0-alpha01")
+ prebuilts(LibraryGroups.TRACING, "1.0.0-beta01")
ignore(LibraryGroups.TRANSITION.group, "transition-ktx")
- prebuilts(LibraryGroups.TRANSITION, "1.3.1")
+ prebuilts(LibraryGroups.TRANSITION, "1.4.0-alpha01")
prebuilts(LibraryGroups.TVPROVIDER, "1.0.0")
prebuilts(LibraryGroups.VECTORDRAWABLE, "vectordrawable", "1.2.0-alpha01")
prebuilts(LibraryGroups.VECTORDRAWABLE, "vectordrawable-animated", "1.1.0")
@@ -149,18 +149,18 @@
prebuilts(LibraryGroups.VERSIONEDPARCELABLE, "versionedparcelable", "1.1.1")
prebuilts(LibraryGroups.VIEWPAGER, "1.0.0")
prebuilts(LibraryGroups.VIEWPAGER2, "1.1.0-alpha01")
- prebuilts(LibraryGroups.WEAR, "wear", "1.1.0-rc01")
+ prebuilts(LibraryGroups.WEAR, "wear", "1.1.0-rc02")
.addStubs("wear/wear_stubs/com.google.android.wearable-stubs.jar")
ignore(LibraryGroups.WEAR.group, "wear-input")
ignore(LibraryGroups.WEAR.group, "wear-input-testing")
- prebuilts(LibraryGroups.WEBKIT, "1.3.0-beta01")
+ prebuilts(LibraryGroups.WEBKIT, "1.3.0-rc01")
ignore(LibraryGroups.WINDOW.group, "window-sidecar")
prebuilts(LibraryGroups.WINDOW, "1.0.0-alpha01")
.addStubs("window/stubs/window-sidecar-release-0.1.0-alpha01.aar")
ignore(LibraryGroups.WORK.group, "work-gcm")
ignore(LibraryGroups.WORK.group, "work-runtime-lint")
ignore(LibraryGroups.WORK.group, "work-rxjava3")
- prebuilts(LibraryGroups.WORK, "2.4.0-beta01")
+ prebuilts(LibraryGroups.WORK, "2.4.0-rc01")
default(Ignore)
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index f6389489..b01ec27 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -59,7 +59,7 @@
const val HILT_ANDROID_TESTING = "com.google.dagger:hilt-android-testing:2.28-alpha"
const val HILT_ANDROID_GRADLE_PLUGIN = "com.google.dagger:hilt-android-gradle-plugin:2.28-alpha"
const val INTELLIJ_ANNOTATIONS = "com.intellij:annotations:12.0"
-const val JAVAPOET = "com.squareup:javapoet:1.12.1"
+const val JAVAPOET = "com.squareup:javapoet:1.13.0"
const val JSR250 = "javax.annotation:javax.annotation-api:1.2"
const val JUNIT = "junit:junit:4.12"
const val KOTLINPOET = "com.squareup:kotlinpoet:1.4.0"
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
index b844f81..bcebce8 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
@@ -21,7 +21,6 @@
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
import org.gradle.workers.WorkerExecutor
import java.io.File
@@ -61,12 +60,6 @@
)
}
- // Declaring outputs prevents Gradle from rerunning this task if the inputs haven't changed
- @OutputFiles
- fun getTaskOutputs(): List<File> {
- return listOf(referenceApi.get().publicApiFile)
- }
-
@TaskAction
fun exec() {
check(bootClasspath.isNotEmpty()) { "Android boot classpath not set." }
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index a1bc83d..a022a62 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -64,6 +64,11 @@
val metalavaJar = getParameters().getMetalavaClasspath().get()
execOperations.javaexec {
+ // Intellij core reflects into java.util.ResourceBundle
+ it.jvmArgs = listOf(
+ "--add-opens",
+ "java.base/java.util=ALL-UNNAMED"
+ )
it.classpath(metalavaJar)
it.main = "com.android.tools.metalava.Driver"
it.args = allArgs
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
index 8fd9dc6..4a965b2 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
@@ -158,6 +158,7 @@
task.api.set(builtApiLocation)
task.dependencyClasspath = javaCompileInputs.dependencyClasspath
task.bootClasspath = javaCompileInputs.bootClasspath
+ task.cacheEvenIfNoOutputs()
task.dependsOn(generateApi)
}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
index e5dd64f..c5b769b 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraGraph.kt
@@ -38,7 +38,8 @@
data class Config(
val camera: CameraId,
- val streams: List<StreamConfig>
+ val streams: List<StreamConfig>,
+ val defaultTemplate: Int
)
/**
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt
index 94efcef..1776548 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Metadata.kt
@@ -20,6 +20,7 @@
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
import android.hardware.camera2.params.StreamConfigurationMap
+import android.view.Surface
import androidx.camera.camera2.pipe.impl.Debug
import java.util.concurrent.ConcurrentHashMap
@@ -33,7 +34,6 @@
*/
interface Metadata {
operator fun <T> get(key: Key<T>): T?
- fun <T> getChecked(key: Key<T>): T
fun <T> getOrDefault(key: Key<T>, default: T): T
/**
@@ -69,7 +69,6 @@
*/
interface CameraMetadata : Metadata, UnsafeWrapper<CameraCharacteristics> {
operator fun <T> get(key: CameraCharacteristics.Key<T>): T?
- fun <T> getChecked(key: CameraCharacteristics.Key<T>): T
fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T
val camera: CameraId
@@ -86,12 +85,35 @@
}
/**
- * RequestMetadata is a wrapper around [CaptureRequest].
+ * RequestMetadata wraps together all of the information about specific CaptureRequest that was
+ * submitted to Camera2.
+ *
+ * <p> This class is distinct from [Request] which is used to configure and issue a request to the
+ * [CameraGraph]. This class will report the actual keys / values that were sent to camera2 (if
+ * different) from the request that was used to create the Camera2 [CaptureRequest].
*/
interface RequestMetadata : Metadata, UnsafeWrapper<CaptureRequest> {
operator fun <T> get(key: CaptureRequest.Key<T>): T?
- fun <T> getChecked(key: CaptureRequest.Key<T>): T
fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T
+
+ /** The actual Camera2 template that was used when creating this [CaptureRequest] */
+ val template: RequestTemplate
+
+ /**
+ * A Map of Surface(s) that were submitted with this CaptureRequest and the StreamId they
+ * were associated with for this request. It's possible that not all streams specified in the
+ * request object are present in this map.
+ */
+ val streams: Map<Surface, StreamId>
+
+ /** The request object that was used to create this [CaptureRequest] */
+ val request: Request
+
+ /** An internal number used to identify a specific [CaptureRequest] */
+ val requestNumber: RequestNumber
+
+ /** The android "sequence id" that is generated by camera2 when submitting [CaptureRequest]'s */
+ val sequenceNumber: SequenceNumber
}
/**
@@ -99,9 +121,51 @@
*/
interface ResultMetadata : Metadata, UnsafeWrapper<CaptureResult> {
operator fun <T> get(key: CaptureResult.Key<T>): T?
- fun <T> getChecked(key: CaptureResult.Key<T>): T
fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T
val camera: CameraId
- val request: RequestMetadata
+ val requestMetadata: RequestMetadata
}
+
+/**
+ * A [RequestTemplate] indicates which preset set list of parameters will be applied to a request by
+ * default. These values are defined by camera2.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class RequestTemplate(val value: Int)
+
+/**
+ * A [SequenceNumber] is the identifier that is returned when a single or repeating capture request
+ * is submitted to the camera and represents that "sequence" of captures.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class SequenceNumber(val value: Int)
+
+/**
+ * A [RequestNumber] is an artificial identifier that is created for each request that is submitted
+ * to the Camera.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class RequestNumber(val value: Long)
+
+/**
+ * A [FrameNumber] is the identifier that represents a specific exposure by the Camera. FrameNumbers
+ * increase within a specific CameraCaptureSession, and are not created until the HAL begins
+ * processing a request.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class FrameNumber(val value: Long)
+
+/**
+ * This is a timestamp from the Camera, and corresponds to the nanosecond exposure time of a Frame.
+ * While the value is expressed in nano-seconds, the precision may be much lower. In addition, the
+ * time-base of the Camera is undefined, although it's common for it to be in either Monotonic or
+ * Realtime.
+ *
+ * <p> Timestamp may differ from timestamps that are obtained from other parts of the Camera and
+ * media systems within the same device. For example, it's common for high frequency sensors to
+ * operate based on a real-time clock, while audio/visual systems commonly operate based on a
+ * monotonic clock.
+ */
+@Suppress("EXPERIMENTAL_FEATURE_WARNING")
+inline class CameraTimestamp(val value: Long)
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt
index 60e4c85..8e24eda 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/Request.kt
@@ -16,10 +16,201 @@
package androidx.camera.camera2.pipe
+import android.hardware.camera2.CaptureFailure
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.CaptureResult
+import android.hardware.camera2.TotalCaptureResult
+import android.view.Surface
+
/**
* An immutable package of settings and outputs needed to capture a single image from the camera
- * device.
+ * device. The exact set of keys and surfaces used in the CaptureRequest builder may be different
+ * from what is specified in a request depending on how the request was submitted and on the
+ * state of the camera.
*/
-interface Request : RequestMetadata {
- val streamIds: List<StreamId>
-}
\ No newline at end of file
+data class Request(
+ val streams: List<StreamId>,
+ val requestParameters: Map<CaptureRequest.Key<*>, Any> = emptyMap(),
+ val extraRequestParameters: Map<Metadata.Key<*>, Any> = emptyMap(),
+ val listeners: List<Listener> = emptyList(),
+ val template: Int? = null
+) {
+
+ /**
+ * This listener is used to observe the state and progress of requests that are submitted to the
+ * [CameraGraph] and can be attached to individual requests.
+ */
+ interface Listener {
+ /**
+ * This event indicates that the camera sensor has started exposing the frame associated
+ * with this Request. The timestamp will either be the beginning or end of the sensors
+ * exposure time depending on the device, and may be in a different timebase from the
+ * timestamps that are returned from the underlying buffers.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureStarted
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ * @param frameNumber the android frame number for this exposure
+ * @param timestamp the android timestamp in nanos for this exposure
+ */
+ fun onStarted(
+ requestMetadata: RequestMetadata,
+ frameNumber: FrameNumber,
+ timestamp: CameraTimestamp
+ ) {
+ }
+
+ /**
+ * This event indicates that the camera sensor has additional information about the frame
+ * associated with this Request. This method may be invoked 0 or more times before the frame
+ * receives onComplete.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureStarted
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ * @param frameNumber the android frame number for this exposure
+ * @param captureResult the current android capture result for this exposure
+ */
+ fun onProgressed(
+ requestMetadata: RequestMetadata,
+ frameNumber: FrameNumber,
+ captureResult: CaptureResult
+ ) {
+ }
+
+ /**
+ * This event indicates that all of the metadata associated with this frame has been
+ * produced. If [onProgressed] was invoked, the values returned in totalCaptureResult be the
+ * same as the values in the prior captureResult(s) for the same frame.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureStarted
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ * @param frameNumber the android frame number for this exposure
+ * @param totalCaptureResult the final android capture result for this exposure
+ */
+ fun onCompleted(
+ requestMetadata: RequestMetadata,
+ frameNumber: FrameNumber,
+ totalCaptureResult: TotalCaptureResult
+ ) {
+ }
+
+ /**
+ * onFailed occurs when a CaptureRequest failed in some way and the frame will not receive
+ * the [onCompleted] callback.
+ *
+ * Surfaces may not received images if "wasImagesCaptured" is set to false.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureFailed
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ * @param frameNumber the android frame number for this exposure
+ * @param captureFailure the android [CaptureFailure] data
+ */
+ fun onFailed(
+ requestMetadata: RequestMetadata,
+ frameNumber: FrameNumber,
+ captureFailure: CaptureFailure
+ ) {
+ }
+
+ /**
+ * onBufferLost occurs when a CaptureRequest failed to create an image for a given output
+ * stream. This method may be invoked multiple times per frame if multiple buffers were
+ * lost. This method may not be invoked when an image is lost in some situations.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureBufferLost
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ * @param frameNumber the android frame number for this exposure
+ * @param stream the internal stream that will not receive a buffer for this frame.
+ */
+ fun onBufferLost(
+ requestMetadata: RequestMetadata,
+ frameNumber: FrameNumber,
+ stream: StreamId
+ ) {
+ }
+
+ /**
+ * This is an artificial callback that will be invoked if a specific request was pending or
+ * had already been submitted to when an abort was requested. The behavior of the request is
+ * undefined if this method is invoked and images or metadata may or may not be produced
+ * for this request. Repeating requests will not receive onAborted.
+ *
+ * @param request the request object
+ */
+ fun onAborted(request: Request) {
+ }
+
+ /**
+ * Invoked after the CaptureRequest(s) have been created, but before the request is
+ * submitted to the camera. This method may be invoked multiple times if the request fails
+ * to submit or if this is a repeating request.
+ *
+ * @param request the request object that was used to create the CaptureRequest
+ * @param requestNumber the internal requestNumber for this request.
+ * @param captureRequest the android CaptureRequest object that was submitted
+ * @param streams the actual Surface objects that were used in this request.
+ */
+ fun onRequestSequenceCreated(
+ request: Request,
+ requestNumber: RequestNumber,
+ captureRequest: CaptureRequest,
+ streams: Map<StreamId, Surface>
+ ) {
+ }
+
+ /**
+ * Invoked after the CaptureRequest(s) has been submitted. This method may be invoked
+ * multiple times if the request was submitted as a repeating request.
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ */
+ fun onRequestSequenceSubmitted(requestMetadata: RequestMetadata) {
+ }
+
+ /**
+ * Invoked by Camera2 if the request was aborted after having been submitted. This method
+ * is distinct from onAborted, which is directly invoked when aborting captures.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureSequenceAborted
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ */
+ fun onRequestSequenceAborted(requestMetadata: RequestMetadata) {
+ }
+
+ /**
+ * Invoked by Camera2 if the request was completed after having been submitted. This method
+ * is distinct from onCompleted which is invoked for each frame when used with a repeating
+ * request.
+ *
+ * @see android.hardware.camera2.CameraCaptureSession.CaptureCallback.onCaptureSequenceCompleted
+ *
+ * @param requestMetadata the data about the camera2 request that was sent to the camera.
+ * @param frameNumber the final frame number of this sequence.
+ */
+ fun onRequestSequenceCompleted(
+ requestMetadata: RequestMetadata,
+ frameNumber: FrameNumber
+ ) {
+ }
+ }
+}
+
+@Suppress("UNCHECKED_CAST")
+private fun <T> Request.getUnchecked(key: Metadata.Key<T>): T? =
+ this.extraRequestParameters[key] as T?
+
+operator fun <T> Request.get(key: Metadata.Key<T>): T? = getUnchecked(key)
+fun <T> Request.getOrDefault(key: Metadata.Key<T>, default: T): T = getUnchecked(key) ?: default
+
+@Suppress("UNCHECKED_CAST")
+private fun <T> Request.getUnchecked(key: CaptureRequest.Key<T>): T? =
+ this.requestParameters[key] as T?
+
+operator fun <T> Request.get(key: CaptureRequest.Key<T>): T? = getUnchecked(key)
+fun <T> Request.getOrDefault(key: CaptureRequest.Key<T>, default: T): T =
+ getUnchecked(key) ?: default
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt
index 1fa50b6..b80f564 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/UnsafeWrapper.kt
@@ -24,4 +24,4 @@
*/
interface UnsafeWrapper<T> {
fun unwrap(): T?
-}
\ No newline at end of file
+}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt
index 3e761b96..48c8bba 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/impl/CameraMetadataImpl.kt
@@ -41,14 +41,10 @@
override fun <T> get(key: Metadata.Key<T>): T? = metadata[key] as T?
@Suppress("UNCHECKED_CAST")
- override fun <T> getChecked(key: Metadata.Key<T>): T = (metadata[key] as T)!!
-
- @Suppress("UNCHECKED_CAST")
override fun <T> getOrDefault(key: Metadata.Key<T>, default: T): T =
metadata[key] as T? ?: default
override fun <T> get(key: CameraCharacteristics.Key<T>): T? = characteristics[key]
- override fun <T> getChecked(key: CameraCharacteristics.Key<T>): T = characteristics[key]!!
override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T =
characteristics[key] ?: default
@@ -138,6 +134,6 @@
private val _streamMap: Lazy<StreamConfigurationMap> =
lazy(LazyThreadSafetyMode.PUBLICATION) {
- getChecked(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
+ get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
}
}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt
index c7292b4..b70cb75 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/CameraPipeTest.kt
@@ -45,7 +45,11 @@
val context = ApplicationProvider.getApplicationContext() as Context
val cameraPipe = CameraPipe(CameraPipe.Config(context))
val cameraGraph = cameraPipe.create(
- CameraGraph.Config(CameraId("0"), listOf())
+ CameraGraph.Config(
+ camera = CameraId("0"),
+ streams = listOf(),
+ defaultTemplate = 0
+ )
)
assertThat(cameraGraph).isNotNull()
}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt
index 6a9088e..0e5a7d7 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/MetadataTest.kt
@@ -27,7 +27,6 @@
import androidx.camera.camera2.pipe.testing.FakeResultMetadata
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -38,20 +37,15 @@
class MetadataTest {
@Test
fun testMetadataCanRetrieveValues() {
- val metadata = FakeMetadata(mapOf(Pair(FakeMetadata.TEST_KEY, 42)))
+ val metadata = FakeMetadata(mapOf(FakeMetadata.TEST_KEY to 42))
assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
assertThat(metadata[FakeMetadata.TEST_KEY_ABSENT]).isNull()
- assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY, 84)).isEqualTo(42)
- assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY_ABSENT, 84)).isEqualTo(84)
-
- try {
- assertThat(metadata.getChecked(FakeMetadata.TEST_KEY_ABSENT))
- fail("Getting an absent key with getChecked should throw.")
- } catch (e: Exception) {
- // Expected
- }
+ assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY, 84))
+ .isEqualTo(42)
+ assertThat(metadata.getOrDefault(FakeMetadata.TEST_KEY_ABSENT, 84))
+ .isEqualTo(84)
}
}
@@ -63,8 +57,8 @@
@Test
fun canRetrieveCameraCharacteristicsOrCameraMetadataViaInterface() {
val metadata = FakeCameraMetadata(
- mapOf(Pair(CameraCharacteristics.LENS_FACING, CameraCharacteristics.LENS_FACING_FRONT)),
- mapOf(Pair(FakeMetadata.TEST_KEY, 42))
+ mapOf(CameraCharacteristics.LENS_FACING to CameraCharacteristics.LENS_FACING_FRONT),
+ mapOf(FakeMetadata.TEST_KEY to 42)
)
assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
@@ -82,16 +76,24 @@
@Test
fun canRetrieveCaptureRequestOrCameraMetadataViaInterface() {
- val metadata = FakeRequestMetadata(
- mapOf(Pair(CaptureRequest.JPEG_QUALITY, 95)),
- mapOf(Pair(FakeMetadata.TEST_KEY, 42))
+ val requestMetadata = FakeRequestMetadata(
+ requestParameters = mapOf(CaptureRequest.JPEG_QUALITY to 95),
+ request = Request(
+ streams = listOf(),
+ requestParameters = mapOf(CaptureRequest.JPEG_QUALITY to 20),
+ extraRequestParameters = mapOf(FakeMetadata.TEST_KEY to 42)
+ )
)
- assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
- assertThat(metadata[FakeMetadata.TEST_KEY_ABSENT]).isNull()
+ assertThat(requestMetadata[CaptureRequest.JPEG_QUALITY]).isEqualTo(95)
+ assertThat(requestMetadata[CaptureRequest.COLOR_CORRECTION_MODE]).isNull()
+ assertThat(requestMetadata[FakeMetadata.TEST_KEY]).isEqualTo(42)
+ assertThat(requestMetadata[FakeMetadata.TEST_KEY_ABSENT]).isNull()
- assertThat(metadata[CaptureRequest.JPEG_QUALITY]).isNotNull()
- assertThat(metadata[CaptureRequest.COLOR_CORRECTION_MODE]).isNull()
+ assertThat(requestMetadata.request[CaptureRequest.JPEG_QUALITY]).isEqualTo(20)
+ assertThat(requestMetadata.request[CaptureRequest.COLOR_CORRECTION_MODE]).isNull()
+ assertThat(requestMetadata.request[FakeMetadata.TEST_KEY]).isEqualTo(42)
+ assertThat(requestMetadata.request[FakeMetadata.TEST_KEY_ABSENT]).isNull()
}
}
@@ -103,9 +105,8 @@
@Test
fun canRetrieveCaptureRequestOrCameraMetadataViaInterface() {
val metadata = FakeResultMetadata(
- FakeRequestMetadata(),
- result = mapOf(Pair(CaptureResult.JPEG_QUALITY, 95)),
- metadata = mapOf(Pair(FakeMetadata.TEST_KEY, 42))
+ resultMetadata = mapOf(CaptureResult.JPEG_QUALITY to 95),
+ extraResultMetadata = mapOf(FakeMetadata.TEST_KEY to 42)
)
assertThat(metadata[FakeMetadata.TEST_KEY]).isNotNull()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/RequestTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/RequestTest.kt
new file mode 100644
index 0000000..8f45dd5
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/RequestTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe
+
+import android.hardware.camera2.CaptureRequest
+import android.os.Build
+import androidx.camera.camera2.pipe.testing.CameraPipeRobolectricTestRunner
+import androidx.camera.camera2.pipe.testing.FakeMetadata
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+
+@SmallTest
+@RunWith(CameraPipeRobolectricTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class RequestTest {
+
+ @Test
+ fun requestHasDefaults() {
+ val request = Request(listOf(StreamId(1)))
+
+ assertThat(request.requestParameters).isEmpty()
+ assertThat(request.extraRequestParameters).isEmpty()
+ assertThat(request.template).isNull()
+ assertThat(request.listeners).isEmpty()
+
+ assertThat(request.streams).contains(StreamId(1))
+ }
+
+ @Test
+ fun canReadCaptureParameters() {
+ val request = Request(
+ listOf(StreamId(1)),
+ requestParameters = mapOf(
+ CaptureRequest.EDGE_MODE to CaptureRequest.EDGE_MODE_HIGH_QUALITY
+ ),
+ extraRequestParameters = mapOf(FakeMetadata.TEST_KEY to 42)
+ )
+
+ // Check with a valid test key
+ assertThat(request[FakeMetadata.TEST_KEY]).isEqualTo(42)
+ assertThat(request.getOrDefault(FakeMetadata.TEST_KEY, default = 24)).isEqualTo(42)
+
+ // Check with an invalid test key
+ assertThat(request[FakeMetadata.TEST_KEY_ABSENT]).isNull()
+ assertThat(request.getOrDefault(FakeMetadata.TEST_KEY_ABSENT, default = 24)).isEqualTo(24)
+
+ // Check with a valid test key
+ assertThat(request.get(CaptureRequest.EDGE_MODE))
+ .isEqualTo(CaptureRequest.EDGE_MODE_HIGH_QUALITY)
+ assertThat(request.getOrDefault(CaptureRequest.EDGE_MODE, default = 24))
+ .isEqualTo(CaptureRequest.EDGE_MODE_HIGH_QUALITY)
+
+ // Check with an invalid test key
+ assertThat(request.get(CaptureRequest.CONTROL_AE_MODE)).isNull()
+ assertThat(
+ request.getOrDefault(
+ CaptureRequest.CONTROL_AE_MODE, default = CaptureRequest.CONTROL_AE_MODE_ON
+ )
+ ).isEqualTo(CaptureRequest.CONTROL_AE_MODE_ON)
+ }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt
index 35a2da1..dccb316 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraGraphImplTest.kt
@@ -40,7 +40,11 @@
@Before
fun setUp() {
- val config = CameraGraph.Config(CameraId("0"), listOf())
+ val config = CameraGraph.Config(
+ camera = CameraId("0"),
+ streams = listOf(),
+ defaultTemplate = 0
+ )
val context = ApplicationProvider.getApplicationContext() as Context
impl = CameraGraphImpl(context, config)
}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt
index c024c71..0b955fe 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/impl/CameraPipeComponentTest.kt
@@ -54,7 +54,11 @@
.build()
val cameraId = CameraId("0")
- val config = CameraGraph.Config(cameraId, listOf())
+ val config = CameraGraph.Config(
+ camera = cameraId,
+ streams = listOf(),
+ defaultTemplate = 0
+ )
val module = CameraGraphModule(config)
val builder = component.cameraGraphComponentBuilder()
builder.cameraGraphModule(module)
@@ -70,7 +74,15 @@
.build()
val graphComponent = component.cameraGraphComponentBuilder()
- .cameraGraphModule(CameraGraphModule(CameraGraph.Config(CameraId("0"), listOf())))
+ .cameraGraphModule(
+ CameraGraphModule(
+ CameraGraph.Config(
+ camera = CameraId("0"),
+ streams = listOf(),
+ defaultTemplate = 0
+ )
+ )
+ )
.build()
val graph = graphComponent.cameraGraph()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt
index f88d2c9..ce66bc1 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/testing/FakeMetadata.kt
@@ -22,11 +22,17 @@
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
import android.hardware.camera2.params.StreamConfigurationMap
+import android.view.Surface
import androidx.camera.camera2.pipe.CameraId
import androidx.camera.camera2.pipe.CameraMetadata
import androidx.camera.camera2.pipe.Metadata
+import androidx.camera.camera2.pipe.Request
import androidx.camera.camera2.pipe.RequestMetadata
+import androidx.camera.camera2.pipe.RequestNumber
+import androidx.camera.camera2.pipe.RequestTemplate
import androidx.camera.camera2.pipe.ResultMetadata
+import androidx.camera.camera2.pipe.SequenceNumber
+import androidx.camera.camera2.pipe.StreamId
/**
* Utility class for interacting with objects that require pre-populated Metadata.
@@ -44,8 +50,6 @@
val value = values[key]
return if (value == null) default else value as T
}
-
- override fun <T> getChecked(key: Metadata.Key<T>): T = (values[key] as T)!!
}
/**
@@ -59,12 +63,9 @@
private val values = characteristics.toMap()
override fun <T> get(key: CameraCharacteristics.Key<T>): T? = values[key] as T?
- override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T {
- val value = values[key]
- return if (value == null) default else value as T
- }
+ override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T =
+ get(key) ?: default
- override fun <T> getChecked(key: CameraCharacteristics.Key<T>): T = (values[key] as T)!!
override val camera = CameraId("Fake")
override val isRedacted = false
override val keys: Set<CameraCharacteristics.Key<*>> = emptySet()
@@ -78,7 +79,8 @@
override fun unwrap(): CameraCharacteristics? {
throw UnsupportedOperationException(
- "FakeCameraMetadata does not wrap CameraCharacteristics")
+ "FakeCameraMetadata does not wrap CameraCharacteristics"
+ )
}
}
@@ -86,21 +88,22 @@
* Utility class for interacting with objects require specific [CaptureRequest] metadata
*/
class FakeRequestMetadata(
- request: Map<CaptureRequest.Key<*>, Any?> = emptyMap(),
- metadata: Map<Metadata.Key<*>, Any?> = emptyMap()
-) : FakeMetadata(metadata), RequestMetadata {
- private val values = request.toMap()
+ private val requestParameters: Map<CaptureRequest.Key<*>, Any?> = emptyMap(),
+ extraRequestParameters: Map<Metadata.Key<*>, Any?> = emptyMap(),
+ override val template: RequestTemplate = RequestTemplate(0),
+ override val streams: Map<Surface, StreamId> = mapOf(),
+ override val request: Request = Request(listOf()),
+ override val requestNumber: RequestNumber = RequestNumber(4321),
+ override val sequenceNumber: SequenceNumber = SequenceNumber(1234)
+) : FakeMetadata(request.extraRequestParameters.plus(extraRequestParameters)), RequestMetadata {
- override fun <T> get(key: CaptureRequest.Key<T>): T? = values[key] as T?
- override fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T {
- val value = values[key]
- return if (value == null) default else value as T
- }
+ override fun <T> get(key: CaptureRequest.Key<T>): T? = requestParameters[key] as T?
+ override fun <T> getOrDefault(key: CaptureRequest.Key<T>, default: T): T = get(key) ?: default
- override fun <T> getChecked(key: CaptureRequest.Key<T>): T = (values[key] as T)!!
override fun unwrap(): CaptureRequest? {
throw UnsupportedOperationException(
- "FakeCameraMetadata does not wrap CameraCharacteristics")
+ "FakeCameraMetadata does not wrap a real CaptureRequest"
+ )
}
}
@@ -108,24 +111,18 @@
* Utility class for interacting with objects require specific [CaptureResult] metadata
*/
class FakeResultMetadata(
- override val request: RequestMetadata,
- override val camera: CameraId = CameraId("Fake"),
- result: Map<CaptureResult.Key<*>, Any?> = emptyMap(),
- metadata: Map<Metadata.Key<*>, Any?> = emptyMap()
-) : FakeMetadata(metadata), ResultMetadata {
+ private val resultMetadata: Map<CaptureResult.Key<*>, Any?> = emptyMap(),
+ extraResultMetadata: Map<Metadata.Key<*>, Any?> = emptyMap(),
+ override val requestMetadata: RequestMetadata = FakeRequestMetadata(),
+ override val camera: CameraId = CameraId("Fake")
+) : FakeMetadata(extraResultMetadata), ResultMetadata {
- private val values = result.toMap()
-
- override fun <T> get(key: CaptureResult.Key<T>): T? = values[key] as T?
- override fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T {
- val value = values[key]
- return if (value == null) default else value as T
- }
-
- override fun <T> getChecked(key: CaptureResult.Key<T>): T = (values[key] as T)!!
+ override fun <T> get(key: CaptureResult.Key<T>): T? = resultMetadata[key] as T?
+ override fun <T> getOrDefault(key: CaptureResult.Key<T>, default: T): T = get(key) ?: default
override fun unwrap(): CaptureResult? {
throw UnsupportedOperationException(
- "FakeCameraMetadata does not wrap CameraCharacteristics")
+ "FakeCameraMetadata does not wrap a real CaptureResult"
+ )
}
}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
index e94f1c2..bd55d88 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
@@ -20,7 +20,6 @@
import static androidx.camera.testing.CoreAppTestUtil.clearDeviceUI;
import static org.junit.Assume.assumeNotNull;
-import static org.junit.Assume.assumeTrue;
import android.app.Instrumentation;
import android.content.Context;
@@ -41,12 +40,13 @@
import androidx.test.filters.SdkSuppress;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.rule.GrantPermissionRule;
import org.junit.After;
import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.concurrent.ExecutionException;
@@ -55,9 +55,9 @@
@LargeTest
public class CameraDisconnectTest {
- @Rule
- public GrantPermissionRule mCameraPermissionRule =
- GrantPermissionRule.grant(android.Manifest.permission.CAMERA);
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+
@Rule
public ActivityTestRule<CameraXTestActivity> mCameraXTestActivityRule =
new ActivityTestRule<>(CameraXTestActivity.class, true, false);
@@ -70,7 +70,6 @@
@Before
public void setUp() {
- assumeTrue(CameraUtil.deviceHasCamera());
CoreAppTestUtil.assumeCompatibleDevice();
Context context = ApplicationProvider.getApplicationContext();
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
index 947d8c1..4324c31 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageAnalysisTest.java
@@ -20,7 +20,6 @@
import static org.junit.Assume.assumeTrue;
-import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Handler;
@@ -48,12 +47,12 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.HashSet;
@@ -78,13 +77,11 @@
private CameraSelector mCameraSelector;
private FakeLifecycleOwner mLifecycleOwner;
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA);
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
@Before
public void setUp() {
- assumeTrue(CameraUtil.deviceHasCamera());
synchronized (mAnalysisResultLock) {
mAnalysisResults = new HashSet<>();
}
@@ -125,49 +122,83 @@
}
@Test
- public void canSupportGuaranteedSize()
+ public void canSupportGuaranteedSizeFront()
throws InterruptedException, CameraInfoUnavailableException {
// CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
// Using for-loop to check both front and back device cameras can support the guaranteed
// 640x480 size.
- for (int i = 0; i <= 1; i++) {
- final int lensFacing = i;
- if (!CameraUtil.hasCameraWithLensFacing(lensFacing)) {
- continue;
- }
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
- // Checks camera device sensor degrees to set correct target rotation value to make sure
- // the exactly matching result size 640x480 can be selected if the device supports it.
- Integer sensorOrientation = CameraUtil.getSensorOrientation(
- CameraSelector.LENS_FACING_BACK);
- boolean isRotateNeeded = (sensorOrientation % 180) != 0;
- ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
- GUARANTEED_RESOLUTION).setTargetRotation(
- isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- mInstrumentation.runOnMainSync(() -> {
- CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
- lensFacing).build();
- CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase);
- mLifecycleOwner.startAndResume();
- useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
- });
+ // Checks camera device sensor degrees to set correct target rotation value to make sure
+ // the exactly matching result size 640x480 can be selected if the device supports it.
+ Integer sensorOrientation = CameraUtil.getSensorOrientation(
+ CameraSelector.LENS_FACING_FRONT);
+ boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+ ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
+ GUARANTEED_RESOLUTION).setTargetRotation(
+ isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+ mInstrumentation.runOnMainSync(() -> {
+ CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+ CameraSelector.LENS_FACING_FRONT).build();
+ CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase);
+ mLifecycleOwner.startAndResume();
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
+ });
+ assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
- assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
-
- synchronized (mAnalysisResultLock) {
- // Check the analyzed image exactly matches 640x480 size. This test can also check
- // whether the guaranteed resolution 640x480 is really supported for YUV_420_888
- // format on the devices when running the test.
- assertThat(GUARANTEED_RESOLUTION).isEqualTo(
- mAnalysisResults.iterator().next().mResolution);
- }
-
- // Reset the environment to run test for the other lens facing camera device.
- mInstrumentation.runOnMainSync(() -> {
- CameraX.unbindAll();
- mLifecycleOwner.pauseAndStop();
- });
+ synchronized (mAnalysisResultLock) {
+ // Check the analyzed image exactly matches 640x480 size. This test can also check
+ // whether the guaranteed resolution 640x480 is really supported for YUV_420_888
+ // format on the devices when running the test.
+ assertThat(GUARANTEED_RESOLUTION).isEqualTo(
+ mAnalysisResults.iterator().next().mResolution);
}
+
+ // Reset the environment to run test for the other lens facing camera device.
+ mInstrumentation.runOnMainSync(() -> {
+ CameraX.unbindAll();
+ mLifecycleOwner.pauseAndStop();
+ });
+ }
+
+ @Test
+ public void canSupportGuaranteedSizeBack()
+ throws InterruptedException, CameraInfoUnavailableException {
+ // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
+ // Using for-loop to check both front and back device cameras can support the guaranteed
+ // 640x480 size.
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
+
+ // Checks camera device sensor degrees to set correct target rotation value to make sure
+ // the exactly matching result size 640x480 can be selected if the device supports it.
+ Integer sensorOrientation = CameraUtil.getSensorOrientation(
+ CameraSelector.LENS_FACING_BACK);
+ boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+ ImageAnalysis useCase = new ImageAnalysis.Builder().setTargetResolution(
+ GUARANTEED_RESOLUTION).setTargetRotation(
+ isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+ mInstrumentation.runOnMainSync(() -> {
+ CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+ CameraSelector.LENS_FACING_BACK).build();
+ CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase);
+ mLifecycleOwner.startAndResume();
+ useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(mHandler), mAnalyzer);
+ });
+ assertThat(mAnalysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue();
+
+ synchronized (mAnalysisResultLock) {
+ // Check the analyzed image exactly matches 640x480 size. This test can also check
+ // whether the guaranteed resolution 640x480 is really supported for YUV_420_888
+ // format on the devices when running the test.
+ assertThat(GUARANTEED_RESOLUTION).isEqualTo(
+ mAnalysisResults.iterator().next().mResolution);
+ }
+
+ // Reset the environment to run test for the other lens facing camera device.
+ mInstrumentation.runOnMainSync(() -> {
+ CameraX.unbindAll();
+ mLifecycleOwner.pauseAndStop();
+ });
}
@Test
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
index f1e8d97..4c6cfdd 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/ImageCaptureTest.java
@@ -88,8 +88,10 @@
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
@@ -113,9 +115,12 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
public final class ImageCaptureTest {
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+
@Rule
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ Manifest.permission.WRITE_EXTERNAL_STORAGE);
private static final Size DEFAULT_RESOLUTION = new Size(640, 480);
private static final Size GUARANTEED_RESOLUTION = new Size(640, 480);
@@ -147,8 +152,6 @@
@Before
@UseExperimental(markerClass = ExperimentalCamera2Interop.class)
public void setUp() throws ExecutionException, InterruptedException {
- assumeTrue(CameraUtil.deviceHasCamera());
-
createDefaultPictureFolderIfNotExist();
Context context = ApplicationProvider.getApplicationContext();
CameraXConfig cameraXConfig = Camera2Config.defaultConfig();
@@ -161,11 +164,6 @@
mLifecycleOwner = new FakeLifecycleOwner();
mMainExecutor = ContextCompat.getMainExecutor(context);
mContentResolver = ApplicationProvider.getApplicationContext().getContentResolver();
-
- // Get the camera ID
- mInstrumentation.runOnMainSync(() -> {
- CameraX.bindToLifecycle(mLifecycleOwner, BACK_SELECTOR);
- });
}
@After
@@ -213,52 +211,95 @@
}
@Test
- public void canSupportGuaranteedSize()
+ public void canSupportGuaranteedSizeFront()
throws CameraInfoUnavailableException, ExecutionException, InterruptedException {
// CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
// Using for-loop to check both front and back device cameras can support the guaranteed
// 640x480 size.
- for (int i = 0; i <= 1; i++) {
- final int lensFacing = i;
- if (!CameraUtil.hasCameraWithLensFacing(lensFacing)) {
- continue;
- }
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
- // Checks camera device sensor degrees to set correct target rotation value to make sure
- // the exactly matching result size 640x480 can be selected if the device supports it.
- Integer sensorOrientation = CameraUtil.getSensorOrientation(BACK_LENS_FACING);
- boolean isRotateNeeded = (sensorOrientation % 180) != 0;
- ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
- GUARANTEED_RESOLUTION).setTargetRotation(
- isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+ // Checks camera device sensor degrees to set correct target rotation value to make sure
+ // the exactly matching result size 640x480 can be selected if the device supports it.
+ Integer sensorOrientation = CameraUtil.getSensorOrientation(
+ CameraSelector.LENS_FACING_FRONT);
+ boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+ ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
+ GUARANTEED_RESOLUTION).setTargetRotation(
+ isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- mInstrumentation.runOnMainSync(
- () -> {
- CameraSelector cameraSelector =
- new CameraSelector.Builder().requireLensFacing(lensFacing).build();
- CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase,
- mRepeatingUseCase);
- mLifecycleOwner.startAndResume();
- });
+ mInstrumentation.runOnMainSync(
+ () -> {
+ CameraSelector cameraSelector =
+ new CameraSelector.Builder().requireLensFacing(
+ CameraSelector.LENS_FACING_FRONT).build();
+ CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase,
+ mRepeatingUseCase);
+ mLifecycleOwner.startAndResume();
+ });
- ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
- OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
- useCase.takePicture(mMainExecutor, callback);
- // Wait for the signal that the image has been captured.
- verify(callback, timeout(10000)).onCaptureSuccess(any(ImageProxy.class));
+ ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
+ OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
+ useCase.takePicture(mMainExecutor, callback);
+ // Wait for the signal that the image has been captured.
+ verify(callback, timeout(10000)).onCaptureSuccess(any(ImageProxy.class));
- // Check the captured image exactly matches 640x480 size. This test can also check
- // whether the guaranteed resolution 640x480 is really supported for JPEG format on the
- // devices when running the test.
- assertEquals(GUARANTEED_RESOLUTION, imageProperties.get().size);
+ // Check the captured image exactly matches 640x480 size. This test can also check
+ // whether the guaranteed resolution 640x480 is really supported for JPEG format on the
+ // devices when running the test.
+ assertEquals(GUARANTEED_RESOLUTION, imageProperties.get().size);
- // Reset the environment to run test for the other lens facing camera device.
- mInstrumentation.runOnMainSync(() -> {
- CameraX.unbindAll();
- mLifecycleOwner.pauseAndStop();
- mRepeatingUseCase = new FakeRepeatingUseCase(mFakeUseCaseConfig);
- });
- }
+ // Reset the environment to run test for the other lens facing camera device.
+ mInstrumentation.runOnMainSync(() -> {
+ CameraX.unbindAll();
+ mLifecycleOwner.pauseAndStop();
+ mRepeatingUseCase = new FakeRepeatingUseCase(mFakeUseCaseConfig);
+ });
+ }
+
+ @Test
+ public void canSupportGuaranteedSizeBack()
+ throws CameraInfoUnavailableException, ExecutionException, InterruptedException {
+ // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
+ // Using for-loop to check both front and back device cameras can support the guaranteed
+ // 640x480 size.
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
+
+ // Checks camera device sensor degrees to set correct target rotation value to make sure
+ // the exactly matching result size 640x480 can be selected if the device supports it.
+ Integer sensorOrientation = CameraUtil.getSensorOrientation(
+ CameraSelector.LENS_FACING_BACK);
+ boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+ ImageCapture useCase = new ImageCapture.Builder().setTargetResolution(
+ GUARANTEED_RESOLUTION).setTargetRotation(
+ isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+
+ mInstrumentation.runOnMainSync(
+ () -> {
+ CameraSelector cameraSelector =
+ new CameraSelector.Builder().requireLensFacing(
+ CameraSelector.LENS_FACING_BACK).build();
+ CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, useCase,
+ mRepeatingUseCase);
+ mLifecycleOwner.startAndResume();
+ });
+
+ ResolvableFuture<ImageProperties> imageProperties = ResolvableFuture.create();
+ OnImageCapturedCallback callback = createMockOnImageCapturedCallback(imageProperties);
+ useCase.takePicture(mMainExecutor, callback);
+ // Wait for the signal that the image has been captured.
+ verify(callback, timeout(10000)).onCaptureSuccess(any(ImageProxy.class));
+
+ // Check the captured image exactly matches 640x480 size. This test can also check
+ // whether the guaranteed resolution 640x480 is really supported for JPEG format on the
+ // devices when running the test.
+ assertEquals(GUARANTEED_RESOLUTION, imageProperties.get().size);
+
+ // Reset the environment to run test for the other lens facing camera device.
+ mInstrumentation.runOnMainSync(() -> {
+ CameraX.unbindAll();
+ mLifecycleOwner.pauseAndStop();
+ mRepeatingUseCase = new FakeRepeatingUseCase(mFakeUseCaseConfig);
+ });
}
@Test
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
index 0785dc3..7f4ca7c 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/PreviewTest.java
@@ -28,7 +28,6 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
-import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.SurfaceTexture;
@@ -52,12 +51,12 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.concurrent.ExecutionException;
@@ -72,9 +71,8 @@
@RunWith(AndroidJUnit4.class)
public final class PreviewTest {
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA);
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
private static final String ANY_THREAD_NAME = "any-thread-name";
private static final Size GUARANTEED_RESOLUTION = new Size(640, 480);
@@ -89,8 +87,6 @@
@Before
public void setUp() throws ExecutionException, InterruptedException {
- assumeTrue(CameraUtil.deviceHasCamera());
-
final Context context = ApplicationProvider.getApplicationContext();
CameraXConfig cameraXConfig = Camera2Config.defaultConfig();
CameraX.initialize(context, cameraXConfig).get();
@@ -230,50 +226,84 @@
}
@Test
- public void canSupportGuaranteedSize()
+ public void canSupportGuaranteedSizeFront()
throws InterruptedException, CameraInfoUnavailableException {
// CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
// Using for-loop to check both front and back device cameras can support the guaranteed
// 640x480 size.
- for (int i = 0; i <= 1; i++) {
- final int lensFacing = i;
- if (!CameraUtil.hasCameraWithLensFacing(lensFacing)) {
- continue;
- }
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
- // Checks camera device sensor degrees to set correct target rotation value to make sure
- // the exactly matching result size 640x480 can be selected if the device supports it.
- Integer sensorOrientation = CameraUtil.getSensorOrientation(
- CameraSelector.LENS_FACING_BACK);
- boolean isRotateNeeded = (sensorOrientation % 180) != 0;
- Preview preview = new Preview.Builder().setTargetResolution(
- GUARANTEED_RESOLUTION).setTargetRotation(
- isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+ // Checks camera device sensor degrees to set correct target rotation value to make sure
+ // the exactly matching result size 640x480 can be selected if the device supports it.
+ Integer sensorOrientation = CameraUtil.getSensorOrientation(
+ CameraSelector.LENS_FACING_FRONT);
+ boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+ Preview preview = new Preview.Builder().setTargetResolution(
+ GUARANTEED_RESOLUTION).setTargetRotation(
+ isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
- mInstrumentation.runOnMainSync(() -> {
- preview.setSurfaceProvider(getSurfaceProvider(null));
- CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
- lensFacing).build();
- CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, preview);
- mLifecycleOwner.startAndResume();
- });
+ mInstrumentation.runOnMainSync(() -> {
+ preview.setSurfaceProvider(getSurfaceProvider(null));
+ CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+ CameraSelector.LENS_FACING_FRONT).build();
+ CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, preview);
+ mLifecycleOwner.startAndResume();
+ });
- // Assert.
- assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
+ // Assert.
+ assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
- // Check whether 640x480 is selected for the preview use case. This test can also check
- // whether the guaranteed resolution 640x480 is really supported for SurfaceTexture
- // format on the devices when running the test.
- assertEquals(GUARANTEED_RESOLUTION, mPreviewResolution);
+ // Check whether 640x480 is selected for the preview use case. This test can also check
+ // whether the guaranteed resolution 640x480 is really supported for SurfaceTexture
+ // format on the devices when running the test.
+ assertEquals(GUARANTEED_RESOLUTION, mPreviewResolution);
- // Reset the environment to run test for the other lens facing camera device.
- mInstrumentation.runOnMainSync(() -> {
- CameraX.unbindAll();
- mLifecycleOwner.pauseAndStop();
- });
- }
+ // Reset the environment to run test for the other lens facing camera device.
+ mInstrumentation.runOnMainSync(() -> {
+ CameraX.unbindAll();
+ mLifecycleOwner.pauseAndStop();
+ });
}
+ @Test
+ public void canSupportGuaranteedSizeBack()
+ throws InterruptedException, CameraInfoUnavailableException {
+ // CameraSelector.LENS_FACING_FRONT/LENS_FACING_BACK are defined as constant int 0 and 1.
+ // Using for-loop to check both front and back device cameras can support the guaranteed
+ // 640x480 size.
+ assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK));
+
+ // Checks camera device sensor degrees to set correct target rotation value to make sure
+ // the exactly matching result size 640x480 can be selected if the device supports it.
+ Integer sensorOrientation = CameraUtil.getSensorOrientation(
+ CameraSelector.LENS_FACING_BACK);
+ boolean isRotateNeeded = (sensorOrientation % 180) != 0;
+ Preview preview = new Preview.Builder().setTargetResolution(
+ GUARANTEED_RESOLUTION).setTargetRotation(
+ isRotateNeeded ? Surface.ROTATION_90 : Surface.ROTATION_0).build();
+
+ mInstrumentation.runOnMainSync(() -> {
+ preview.setSurfaceProvider(getSurfaceProvider(null));
+ CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(
+ CameraSelector.LENS_FACING_BACK).build();
+ CameraX.bindToLifecycle(mLifecycleOwner, cameraSelector, preview);
+ mLifecycleOwner.startAndResume();
+ });
+
+ // Assert.
+ assertThat(mSurfaceFutureSemaphore.tryAcquire(10, TimeUnit.SECONDS)).isTrue();
+
+ // Check whether 640x480 is selected for the preview use case. This test can also check
+ // whether the guaranteed resolution 640x480 is really supported for SurfaceTexture
+ // format on the devices when running the test.
+ assertEquals(GUARANTEED_RESOLUTION, mPreviewResolution);
+
+ // Reset the environment to run test for the other lens facing camera device.
+ mInstrumentation.runOnMainSync(() -> {
+ CameraX.unbindAll();
+ mLifecycleOwner.pauseAndStop();
+ });
+ }
@Test
public void setMultipleNonNullSurfaceProviders_getsFrame() throws InterruptedException {
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
index 376d434..00704c1 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/UseCaseCombinationTest.java
@@ -20,9 +20,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assume.assumeTrue;
-
-import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.SurfaceTexture;
@@ -46,12 +43,12 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.concurrent.ExecutionException;
@@ -66,17 +63,14 @@
public final class UseCaseCombinationTest {
private static final CameraSelector DEFAULT_SELECTOR = CameraSelector.DEFAULT_BACK_CAMERA;
private final MutableLiveData<Long> mAnalysisResult = new MutableLiveData<>();
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO);
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private Semaphore mSemaphore;
private FakeLifecycleOwner mLifecycle;
@Before
public void setUp() {
- assumeTrue(CameraUtil.deviceHasCamera());
-
final Context context = ApplicationProvider.getApplicationContext();
final CameraXConfig config = Camera2Config.defaultConfig();
CameraX.initialize(context, config);
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
index 8b6bfd4..d3daaa4 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
@@ -20,7 +20,6 @@
import static junit.framework.TestCase.assertTrue;
-import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -29,7 +28,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.internal.verification.VerificationModeFactory.times;
-import android.Manifest;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraDevice;
import android.media.ImageReader;
@@ -74,7 +72,6 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.rule.GrantPermissionRule;
import com.google.common.util.concurrent.ListenableFuture;
@@ -82,8 +79,9 @@
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@@ -119,9 +117,9 @@
private static CameraFactory sCameraFactory;
static ExecutorService sCameraExecutor;
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA);
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
+
private ArrayList<FakeUseCase> mFakeUseCases = new ArrayList<>();
private Camera2CameraImpl mCamera2CameraImpl;
@@ -150,7 +148,6 @@
@Before
public void setup() throws CameraUnavailableException {
- assumeTrue(CameraUtil.deviceHasCamera());
mMockOnImageAvailableListener = Mockito.mock(ImageReader.OnImageAvailableListener.class);
mSessionStateCallback = new SemaphoreReleasingCamera2Callbacks.SessionStateCallback();
mCameraId = CameraUtil.getCameraIdWithLensFacing(DEFAULT_LENS_FACING);
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
index adf56c7..d5be316 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2ImplCameraXTest.java
@@ -26,7 +26,6 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
-import android.Manifest;
import android.app.Instrumentation;
import android.content.Context;
import android.hardware.camera2.CameraAccessException;
@@ -42,6 +41,7 @@
import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks;
import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks.DeviceStateCallback;
import androidx.camera.camera2.internal.util.SemaphoreReleasingCamera2Callbacks.SessionCaptureCallback;
+import androidx.camera.camera2.interop.Camera2CameraInfo;
import androidx.camera.camera2.interop.Camera2Interop;
import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
import androidx.camera.core.Camera;
@@ -52,7 +52,6 @@
import androidx.camera.core.CameraX;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
-import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.CameraUtil;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
@@ -64,12 +63,12 @@
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.Arrays;
@@ -105,9 +104,8 @@
mAnalysisResult2.postValue(image.getImageInfo().getTimestamp());
image.close();
};
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA);
+ @ClassRule
+ public static TestRule sCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -125,7 +123,6 @@
@Before
public void setUp() {
- assumeTrue(CameraUtil.deviceHasCamera());
Context context = ApplicationProvider.getApplicationContext();
CameraX.initialize(context, Camera2Config.defaultConfig());
mLifecycle = new FakeLifecycleOwner();
@@ -610,7 +607,7 @@
useCase);
List<String> camera2IdList = Arrays.asList(CameraUtil.getCameraManager().getCameraIdList());
- assertThat(((CameraInternal) camera).getCameraInfoInternal().getCameraId()).isEqualTo(
+ assertThat(Camera2CameraInfo.extractCameraId(camera.getCameraInfo())).isEqualTo(
camera2IdList.iterator().next());
}
@@ -624,7 +621,7 @@
new CameraSelector.Builder().requireLensFacing(DEFAULT_LENS_FACING).build(),
useCase);
- assertThat(((CameraInternal) camera).getCameraInfoInternal().getCameraId()).isEqualTo(
+ assertThat(Camera2CameraInfo.extractCameraId(camera.getCameraInfo())).isEqualTo(
CameraUtil.getCameraIdWithLensFacing(DEFAULT_LENS_FACING));
}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
index 79a7d07..b43fdb4 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
@@ -21,7 +21,6 @@
import static junit.framework.TestCase.assertTrue;
import static junit.framework.TestCase.fail;
-import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -32,7 +31,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import android.Manifest;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
@@ -66,15 +64,15 @@
import androidx.core.os.HandlerCompat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
-import androidx.test.rule.GrantPermissionRule;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.After;
import org.junit.AssumptionViolatedException;
import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
@@ -107,14 +105,12 @@
private final List<CaptureSession> mCaptureSessions = new ArrayList<>();
- @Rule
- public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(
- Manifest.permission.CAMERA);
+ @ClassRule
+ public static TestRule sUseCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
@Before
public void setup() throws CameraAccessException, InterruptedException,
AssumptionViolatedException, TimeoutException, ExecutionException {
- assumeTrue(CameraUtil.deviceHasCamera());
mTestParameters0 = new CaptureSessionTestParameters("mTestParameters0");
mTestParameters1 = new CaptureSessionTestParameters("mTestParameters1");
mCameraDeviceHolder = CameraUtil.getCameraDevice();
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
index 3a9dfc0..b10101c 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
@@ -56,9 +56,11 @@
import androidx.camera.core.impl.SurfaceConfig.ConfigType;
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.impl.VideoCaptureConfig;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.testing.CameraUtil;
import androidx.camera.testing.Configs;
import androidx.camera.testing.StreamConfigurationMapUtil;
+import androidx.camera.testing.SurfaceTextureProvider;
import androidx.camera.testing.fakes.FakeCamera;
import androidx.camera.testing.fakes.FakeCameraFactory;
import androidx.camera.testing.fakes.FakeLifecycleOwner;
@@ -486,6 +488,9 @@
final Preview preview = new Preview.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.build();
+ preview.setSurfaceProvider(CameraXExecutors.directExecutor(),
+ SurfaceTextureProvider.createSurfaceTextureProvider(mock(
+ SurfaceTextureProvider.SurfaceTextureCallback.class)));
// Ensure we are bound to a camera to ensure aspect ratio correction is applied.
FakeLifecycleOwner fakeLifecycle = new FakeLifecycleOwner();
@@ -534,6 +539,9 @@
mContext, CAMERA_ID, mMockCamcorderProfileHelper);
Preview preview = new Preview.Builder().build();
+ preview.setSurfaceProvider(CameraXExecutors.directExecutor(),
+ SurfaceTextureProvider.createSurfaceTextureProvider(mock(
+ SurfaceTextureProvider.SurfaceTextureCallback.class)));
ImageCapture imageCapture = new ImageCapture.Builder().build();
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
index 4c87c16e..71f0a69 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/CameraXTest.java
@@ -240,10 +240,10 @@
@Test
@UiThreadTest
- public void bind_createsNewUseCaseMediator() {
+ public void bind_createsNewLifecycleCamera() {
initCameraX();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR, new FakeUseCase());
- // One observer is the use case mediator. The other observer removes the use case upon the
+ // One observer is the LifecycleCamera. The other observer removes the use case upon the
// lifecycle's destruction.
assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
}
@@ -275,7 +275,7 @@
@Test
@UiThreadTest
- public void bind_createsDifferentUseCaseMediators_forDifferentLifecycles() {
+ public void bind_createsDifferentLifecycleCameras_forDifferentLifecycles() {
initCameraX();
CameraX.bindToLifecycle(mLifecycle, CAMERA_SELECTOR,
new FakeUseCaseConfig.Builder().setTargetName("config0").build());
@@ -284,7 +284,7 @@
CameraX.bindToLifecycle(anotherLifecycle, CAMERA_SELECTOR,
new FakeUseCaseConfig.Builder().setTargetName("config1").build());
- // One observer is the use case mediator. The other observer removes the use case upon the
+ // One observer is the LifecycleCamera. The other observer removes the use case upon the
// lifecycle's destruction.
assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
assertThat(anotherLifecycle.getObserverCount()).isEqualTo(2);
@@ -373,19 +373,6 @@
}
@Test
- @UiThreadTest
- public void bindUseCases_canUpdateUseCase() {
- initCameraX();
- FakeUseCaseConfig config0 = new FakeUseCaseConfig.Builder().getUseCaseConfig();
- FakeUseCase fakeUseCase = new FakeUseCase(config0);
-
- Camera camera = CameraX.bindToLifecycle(mLifecycle, CameraSelector.DEFAULT_BACK_CAMERA,
- fakeUseCase);
-
- assertThat(fakeUseCase.getCamera()).isEqualTo(camera);
- }
-
- @Test
public void requestingDefaultConfiguration_returnsDefaultConfiguration() {
initCameraX();
// Requesting a default configuration will throw if CameraX is not initialized.
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
similarity index 98%
rename from camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisTest.java
rename to camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
index 27801a3bf..c165a4e 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageAnalysisDeviceTest.java
@@ -41,7 +41,8 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class ImageAnalysisTest {
+public class ImageAnalysisDeviceTest {
+
private final CameraInternal mMockCameraInternal = mock(CameraInternal.class);
private final ImageAnalysis.Analyzer mMockAnalyzer = mock(ImageAnalysis.Analyzer.class);
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
index 4cf2448..94de7cb 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageCaptureTest.java
@@ -27,10 +27,13 @@
import android.util.Size;
import androidx.camera.core.impl.CaptureConfig;
+import androidx.camera.core.impl.ImageCaptureConfig;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.camera.testing.fakes.FakeAppConfig;
import androidx.camera.testing.fakes.FakeCamera;
import androidx.camera.testing.fakes.FakeCameraControl;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
@@ -42,6 +45,8 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -51,7 +56,7 @@
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ImageCaptureTest {
- private FakeCamera mFakeCamera;
+ private CameraUseCaseAdapter mCameraUseCaseAdapter;
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
@Before
@@ -62,7 +67,17 @@
Context context = ApplicationProvider.getApplicationContext();
CameraX.initialize(context, cameraXConfig).get();
- mFakeCamera = new FakeCamera();
+ FakeCamera fakeCamera = new FakeCamera("fakeCameraId");
+
+ FakeCameraDeviceSurfaceManager fakeCameraDeviceSurfaceManager =
+ new FakeCameraDeviceSurfaceManager();
+ fakeCameraDeviceSurfaceManager.setSuggestedResolution("fakeCameraId",
+ ImageCaptureConfig.class,
+ new Size(640, 480));
+
+ mCameraUseCaseAdapter = new CameraUseCaseAdapter(fakeCamera,
+ new LinkedHashSet<>(Collections.singleton(fakeCamera)),
+ fakeCameraDeviceSurfaceManager);
}
@After
@@ -74,12 +89,17 @@
public void onCaptureCancelled_onErrorCAMERA_CLOSED() {
ImageCapture imageCapture = createImageCapture();
- mInstrumentation.runOnMainSync(() -> bind(imageCapture));
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ mCameraUseCaseAdapter.addUseCases(Collections.singleton(imageCapture));
+ } catch (CameraUseCaseAdapter.CameraException ignore) {
+ }
+ });
ImageCapture.OnImageCapturedCallback callback = mock(
ImageCapture.OnImageCapturedCallback.class);
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mFakeCamera.getCameraControlInternal());
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
// Notify the cancel after the capture request has been successfully submitted
@@ -100,12 +120,17 @@
public void onRequestFailed_OnErrorCAPTURE_FAILED() {
ImageCapture imageCapture = createImageCapture();
- mInstrumentation.runOnMainSync(() -> bind(imageCapture));
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ mCameraUseCaseAdapter.addUseCases(Collections.singleton(imageCapture));
+ } catch (CameraUseCaseAdapter.CameraException ignore) {
+ }
+ });
ImageCapture.OnImageCapturedCallback callback = mock(
ImageCapture.OnImageCapturedCallback.class);
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mFakeCamera.getCameraControlInternal());
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
fakeCameraControl.setOnNewCaptureRequestListener(captureConfigs -> {
// Notify the failure after the capture request has been successfully submitted
fakeCameraControl.notifyAllRequestsOnCaptureFailed();
@@ -128,9 +153,14 @@
public void captureWithMinLatency_jpegQualityIs95() throws InterruptedException {
// Arrange.
ImageCapture imageCapture = createImageCapture();
- mInstrumentation.runOnMainSync(() -> bind(imageCapture));
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ mCameraUseCaseAdapter.addUseCases(Collections.singleton(imageCapture));
+ } catch (CameraUseCaseAdapter.CameraException ignore) {
+ }
+ });
FakeCameraControl fakeCameraControl =
- ((FakeCameraControl) mFakeCamera.getCameraControlInternal());
+ ((FakeCameraControl) mCameraUseCaseAdapter.getCameraControlInternal());
FakeCameraControl.OnNewCaptureRequestListener mockCaptureRequestListener =
mock(FakeCameraControl.OnNewCaptureRequestListener.class);
@@ -169,11 +199,4 @@
})
.build();
}
-
- // TODO(b/147698557) Should be removed when the binding of UseCase to Camera is simplified.
- private void bind(UseCase useCase) {
- // Sets bound camera to use case.
- useCase.onAttach(mFakeCamera);
- useCase.updateSuggestedResolution(new Size(640, 480));
- }
}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraRepositoryTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraRepositoryTest.java
new file mode 100644
index 0000000..2e0773d
--- /dev/null
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraRepositoryTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.camera.core.impl.CameraInternal;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.camera.testing.fakes.FakeCamera;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
+import androidx.camera.testing.fakes.FakeLifecycleOwner;
+import androidx.camera.testing.fakes.FakeUseCase;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class LifecycleCameraRepositoryTest {
+
+ private FakeLifecycleOwner mLifecycle;
+ private LifecycleCameraRepository mRepository;
+ private CameraUseCaseAdapter mCameraUseCaseAdapter;
+ private LinkedHashSet<CameraInternal> mCameraSet;
+
+ @Before
+ public void setUp() {
+ mLifecycle = new FakeLifecycleOwner();
+ mRepository = new LifecycleCameraRepository();
+ CameraInternal camera = new FakeCamera();
+ mCameraSet = new LinkedHashSet<>(Collections.singleton(camera));
+ mCameraUseCaseAdapter = new CameraUseCaseAdapter(camera,
+ mCameraSet,
+ new FakeCameraDeviceSurfaceManager());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void throwException_ifTryingToCreateWithExistingIdentifier() {
+ LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+ LifecycleCamera secondLifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+
+ assertThat(firstLifecycleCamera).isSameInstanceAs(secondLifecycleCamera);
+ }
+
+ @Test
+ public void differentLifecycleCamerasAreCreated_forDifferentLifecycles() {
+ LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+ FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
+ LifecycleCamera secondLifecycleCamera =
+ mRepository.createLifecycleCamera(secondLifecycle,
+ mCameraUseCaseAdapter);
+
+ assertThat(firstLifecycleCamera).isNotEqualTo(secondLifecycleCamera);
+ }
+
+ @Test
+ public void differentLifecycleCamerasAreCreated_forDifferentCameraSets() {
+ LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+
+ CameraInternal fakeCamera = new FakeCamera("other");
+ CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(fakeCamera,
+ new LinkedHashSet<>(Collections.singleton(fakeCamera)),
+ new FakeCameraDeviceSurfaceManager());
+
+ LifecycleCamera secondLifecycleCamera =
+ mRepository.createLifecycleCamera(mLifecycle,
+ cameraUseCaseAdapter);
+
+ assertThat(firstLifecycleCamera).isNotEqualTo(secondLifecycleCamera);
+ }
+
+ @Test
+ public void useCaseIsCleared_whenLifecycleIsDestroyed() throws
+ CameraUseCaseAdapter.CameraException {
+ LifecycleCamera lifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+ FakeUseCase useCase = new FakeUseCase();
+ lifecycleCamera.bind(Collections.singleton(useCase));
+
+ assertThat(useCase.isCleared()).isFalse();
+
+ mLifecycle.destroy();
+
+ assertThat(useCase.isCleared()).isTrue();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void exception_whenCreatingWithDestroyedLifecycle() {
+ mLifecycle.destroy();
+
+ // Should throw IllegalArgumentException
+ mRepository.createLifecycleCamera(mLifecycle, mCameraUseCaseAdapter);
+ }
+
+ @Test
+ public void lifecycleCameraIsStopped_whenNewLifecycleIsStarted() {
+ // Starts first lifecycle and check LifecycleCamera active state is true.
+ LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+ mLifecycle.start();
+ assertThat(firstLifecycleCamera.isActive()).isTrue();
+
+ // Starts second lifecycle and check previous LifecycleCamera is stopped.
+ FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
+ LifecycleCamera secondLifecycleCamera =
+ mRepository.createLifecycleCamera(
+ secondLifecycle, mCameraUseCaseAdapter);
+ secondLifecycle.start();
+ assertThat(secondLifecycleCamera.isActive()).isTrue();
+ assertThat(firstLifecycleCamera.isActive()).isFalse();
+ }
+
+ @Test
+ public void lifecycleCameraOf2ndActiveLifecycleIsStarted_when1stActiveLifecycleIsStopped() {
+ // Starts first lifecycle and check LifecycleCamera active state is true.
+ LifecycleCamera firstLifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+ mLifecycle.start();
+ assertThat(firstLifecycleCamera.isActive()).isTrue();
+
+ // Starts second lifecycle and check previous LifecycleCamera is stopped.
+ FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
+ LifecycleCamera secondLifecycleCamera =
+ mRepository.createLifecycleCamera(
+ secondLifecycle, mCameraUseCaseAdapter);
+ secondLifecycle.start();
+ assertThat(secondLifecycleCamera.isActive()).isTrue();
+ assertThat(firstLifecycleCamera.isActive()).isFalse();
+
+ // Stops second lifecycle and check previous LifecycleCamera is started again.
+ secondLifecycle.stop();
+ assertThat(secondLifecycleCamera.isActive()).isFalse();
+ assertThat(firstLifecycleCamera.isActive()).isTrue();
+ }
+
+ @Test
+ public void retrievesExistingCamera() {
+ LifecycleCamera lifecycleCamera = mRepository.createLifecycleCamera(
+ mLifecycle, mCameraUseCaseAdapter);
+ CameraUseCaseAdapter.CameraId cameraId = CameraUseCaseAdapter.generateCameraId(mCameraSet);
+ LifecycleCamera retrieved = mRepository.getLifecycleCamera(mLifecycle, cameraId);
+
+ assertThat(lifecycleCamera).isSameInstanceAs(retrieved);
+ }
+
+ @Test
+ public void keys() {
+ LifecycleCameraRepository.Key key0 = LifecycleCameraRepository.Key.create(mLifecycle,
+ mCameraUseCaseAdapter.getCameraId());
+ LifecycleCameraRepository.Key key1 = LifecycleCameraRepository.Key.create(mLifecycle,
+ CameraUseCaseAdapter.generateCameraId(mCameraSet));
+
+ Map<LifecycleCameraRepository.Key, LifecycleOwner> map = new HashMap<>();
+ map.put(key0, mLifecycle);
+ assertThat(map).containsKey(key1);
+
+ assertThat(key0).isEqualTo(key1);
+ }
+}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraTest.java
new file mode 100644
index 0000000..0ac18b8
--- /dev/null
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/LifecycleCameraTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.camera.testing.fakes.FakeCamera;
+import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
+import androidx.camera.testing.fakes.FakeLifecycleOwner;
+import androidx.camera.testing.fakes.FakeUseCase;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LifecycleCameraTest {
+ private LifecycleCamera mLifecycleCamera;
+ private FakeLifecycleOwner mLifecycleOwner;
+ private CameraUseCaseAdapter mCameraUseCaseAdapter;
+ private FakeCamera mFakeCamera;
+ private FakeUseCase mFakeUseCase;
+
+ @Before
+ public void setUp() {
+ mLifecycleOwner = new FakeLifecycleOwner();
+ mFakeCamera = new FakeCamera();
+ mCameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ new LinkedHashSet<>(Collections.singleton(mFakeCamera)),
+ new FakeCameraDeviceSurfaceManager());
+ mFakeUseCase = new FakeUseCase();
+ }
+
+ @Test
+ public void lifecycleCameraCanBeMadeObserverOfLifecycle() {
+ assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
+
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void lifecycleCameraCanStopObservingALifecycle() {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
+
+ mLifecycleCamera.release();
+
+ assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void lifecycleCameraCanBeReleasedMultipleTimes() {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ mLifecycleCamera.release();
+ mLifecycleCamera.release();
+ }
+
+ @Test
+ public void lifecycleStart_triggersOnActive() {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ mLifecycleOwner.start();
+
+ assertThat(mLifecycleCamera.isActive()).isTrue();
+ }
+
+ @Test
+ public void lifecycleStop_triggersOnInactive() {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ mLifecycleOwner.start();
+
+ mLifecycleOwner.stop();
+
+ assertThat(mLifecycleCamera.isActive()).isFalse();
+ }
+
+ @Test
+ public void lifecycleStart_doesNotTriggerOnActiveIfSuspended() {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ mLifecycleCamera.suspend();
+ mLifecycleOwner.start();
+
+ assertThat(mLifecycleCamera.isActive()).isFalse();
+ }
+
+ @Test
+ public void unsuspendOfStartedLifecycle_triggersOnActive() {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+
+ mLifecycleCamera.suspend();
+ mLifecycleOwner.start();
+ mLifecycleCamera.unsuspend();
+
+ assertThat(mLifecycleCamera.isActive()).isTrue();
+ }
+
+ @Test
+ public void bind_willBindToCameraInternal() throws CameraUseCaseAdapter.CameraException {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+ mLifecycleOwner.start();
+
+ mLifecycleCamera.bind(Collections.singleton(mFakeUseCase));
+
+ assertThat(mFakeCamera.getAttachedUseCases()).containsExactly(mFakeUseCase);
+ }
+
+ @Test
+ public void unbind_willUnbindFromCameraInternal() throws CameraUseCaseAdapter.CameraException {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+ mLifecycleOwner.start();
+
+ mLifecycleCamera.bind(Collections.singleton(mFakeUseCase));
+ mLifecycleCamera.unbind(Collections.singletonList(mFakeUseCase));
+
+ assertThat(mFakeCamera.getAttachedUseCases()).isEmpty();
+ }
+
+ @Test
+ public void unbindAll_willUnbindFromCameraInternal()
+ throws CameraUseCaseAdapter.CameraException {
+ mLifecycleCamera = new LifecycleCamera(mLifecycleOwner, mCameraUseCaseAdapter);
+ mLifecycleOwner.start();
+
+ mLifecycleCamera.bind(Collections.singleton(mFakeUseCase));
+ mLifecycleCamera.unbindAll();
+
+ assertThat(mFakeCamera.getAttachedUseCases()).isEmpty();
+ }
+}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorLifecycleControllerTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorLifecycleControllerTest.java
deleted file mode 100644
index 07ac7d0..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorLifecycleControllerTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import androidx.camera.core.impl.UseCaseMediator;
-import androidx.camera.testing.fakes.FakeLifecycleOwner;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class UseCaseMediatorLifecycleControllerTest {
- private final UseCaseMediator.StateChangeCallback mMockCallback =
- Mockito.mock(UseCaseMediator.StateChangeCallback.class);
- private UseCaseMediatorLifecycleController mUseCaseMediatorLifecycleController;
- private FakeLifecycleOwner mLifecycleOwner;
-
- @Before
- public void setUp() {
- mLifecycleOwner = new FakeLifecycleOwner();
- }
-
- @Test
- public void mediatorCanBeMadeObserverOfLifecycle() {
- assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
-
- mUseCaseMediatorLifecycleController =
- new UseCaseMediatorLifecycleController(
- mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-
- assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
- }
-
- @Test
- public void mediatorCanStopObservingALifeCycle() {
- mUseCaseMediatorLifecycleController =
- new UseCaseMediatorLifecycleController(
- mLifecycleOwner.getLifecycle(), new UseCaseMediator());
- assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(1);
-
- mUseCaseMediatorLifecycleController.release();
-
- assertThat(mLifecycleOwner.getObserverCount()).isEqualTo(0);
- }
-
- @Test
- public void mediatorCanBeReleasedMultipleTimes() {
- mUseCaseMediatorLifecycleController =
- new UseCaseMediatorLifecycleController(
- mLifecycleOwner.getLifecycle(), new UseCaseMediator());
-
- mUseCaseMediatorLifecycleController.release();
- mUseCaseMediatorLifecycleController.release();
- }
-
- @Test
- public void lifecycleStart_triggersOnActive() {
- mUseCaseMediatorLifecycleController =
- new UseCaseMediatorLifecycleController(
- mLifecycleOwner.getLifecycle(), new UseCaseMediator());
- mUseCaseMediatorLifecycleController.getUseCaseMediator().setListener(mMockCallback);
-
- mLifecycleOwner.start();
-
- verify(mMockCallback, times(1))
- .onActive(mUseCaseMediatorLifecycleController.getUseCaseMediator());
- }
-
- @Test
- public void lifecycleStop_triggersOnInactive() {
- mUseCaseMediatorLifecycleController =
- new UseCaseMediatorLifecycleController(
- mLifecycleOwner.getLifecycle(), new UseCaseMediator());
- mUseCaseMediatorLifecycleController.getUseCaseMediator().setListener(mMockCallback);
- mLifecycleOwner.start();
-
- mLifecycleOwner.stop();
-
- verify(mMockCallback, times(1))
- .onInactive(mUseCaseMediatorLifecycleController.getUseCaseMediator());
- }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java
deleted file mode 100644
index 46f919a..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/UseCaseMediatorRepositoryTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.camera.core.internal.CameraUseCaseAdapter;
-import androidx.camera.testing.fakes.FakeCamera;
-import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
-import androidx.camera.testing.fakes.FakeLifecycleOwner;
-import androidx.camera.testing.fakes.FakeUseCase;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Collections;
-import java.util.Map;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class UseCaseMediatorRepositoryTest {
-
- private FakeLifecycleOwner mLifecycle;
- private UseCaseMediatorRepository mRepository;
- private Map<LifecycleOwner, UseCaseMediatorLifecycleController> mUseCasesMap;
- private CameraUseCaseAdapter mCameraUseCaseAdapter;
-
- @Before
- public void setUp() {
- mLifecycle = new FakeLifecycleOwner();
- mRepository = new UseCaseMediatorRepository();
- mUseCasesMap = mRepository.getUseCasesMap();
- mCameraUseCaseAdapter = new CameraUseCaseAdapter(new FakeCamera(),
- new FakeCameraDeviceSurfaceManager());
- }
-
- @Test
- public void repositoryStartsEmpty() {
- assertThat(mUseCasesMap).isEmpty();
- }
-
- @Test
- public void newUseCaseMediatorIsCreated_whenNoMediatorExistsForLifecycleInRepository() {
- UseCaseMediatorLifecycleController mediator = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
-
- assertThat(mUseCasesMap).containsExactly(mLifecycle, mediator);
- }
-
- @Test
- public void existingUseCaseMediatorIsReturned_whenMediatorExistsForLifecycleInRepository() {
- UseCaseMediatorLifecycleController firstMediator = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
- UseCaseMediatorLifecycleController secondMediator = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
-
- assertThat(firstMediator).isSameInstanceAs(secondMediator);
- assertThat(mUseCasesMap).containsExactly(mLifecycle, firstMediator);
- }
-
- @Test
- public void differentUseCaseMediatorsAreCreated_forDifferentLifecycles() {
- UseCaseMediatorLifecycleController firstMediator = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
- FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
- UseCaseMediatorLifecycleController secondMediator =
- mRepository.getOrCreateUseCaseMediator(secondLifecycle);
-
- assertThat(mUseCasesMap)
- .containsExactly(mLifecycle, firstMediator, secondLifecycle, secondMediator);
- }
-
- @Test
- public void useCaseMediatorObservesLifecycle() {
- mRepository.getOrCreateUseCaseMediator(mLifecycle);
-
- // One observer is the use case mediator. The other observer removes the use case from the
- // repository when the lifecycle is destroyed.
- assertThat(mLifecycle.getObserverCount()).isEqualTo(2);
- }
-
- @Test
- public void useCaseMediatorIsRemovedFromRepository_whenLifecycleIsDestroyed() {
- mRepository.getOrCreateUseCaseMediator(mLifecycle);
- mLifecycle.destroy();
-
- assertThat(mUseCasesMap).isEmpty();
- }
-
- @Test
- public void useCaseIsCleared_whenLifecycleIsDestroyed()
- throws CameraUseCaseAdapter.CameraException {
- UseCaseMediatorLifecycleController mediator = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
- FakeUseCase useCase = new FakeUseCase();
- mediator.getUseCaseMediator().addUseCase(useCase);
-
- mCameraUseCaseAdapter.attachUseCases(Collections.singleton(useCase));
-
- assertThat(useCase.isCleared()).isFalse();
-
- mLifecycle.destroy();
-
- assertThat(useCase.isCleared()).isTrue();
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void exception_whenCreatingWithDestroyedLifecycle() {
- mLifecycle.destroy();
-
- // Should throw IllegalArgumentException
- mRepository.getOrCreateUseCaseMediator(mLifecycle);
- }
-
- @Test
- public void useCaseMediatorIsStopped_whenNewLifecycleIsStarted() {
- // Starts first lifecycle and check UseCaseMediator active state is true.
- UseCaseMediatorLifecycleController firstController = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
- mLifecycle.start();
- assertThat(firstController.getUseCaseMediator().isActive()).isTrue();
-
- // Starts second lifecycle and check previous UseCaseMediator is stopped.
- FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
- UseCaseMediatorLifecycleController secondController =
- mRepository.getOrCreateUseCaseMediator(
- secondLifecycle);
- secondLifecycle.start();
- assertThat(secondController.getUseCaseMediator().isActive()).isTrue();
- assertThat(firstController.getUseCaseMediator().isActive()).isFalse();
- }
-
- @Test
- public void useCaseMediatorOf2ndActiveLifecycleIsStarted_when1stActiveLifecycleIsStopped() {
- // Starts first lifecycle and check UseCaseMediator active state is true.
- UseCaseMediatorLifecycleController firstController = mRepository.getOrCreateUseCaseMediator(
- mLifecycle);
- mLifecycle.start();
- assertThat(firstController.getUseCaseMediator().isActive()).isTrue();
-
- // Starts second lifecycle and check previous UseCaseMediator is stopped.
- FakeLifecycleOwner secondLifecycle = new FakeLifecycleOwner();
- UseCaseMediatorLifecycleController secondController =
- mRepository.getOrCreateUseCaseMediator(
- secondLifecycle);
- secondLifecycle.start();
- assertThat(secondController.getUseCaseMediator().isActive()).isTrue();
- assertThat(firstController.getUseCaseMediator().isActive()).isFalse();
-
- // Stops second lifecycle and check previous UseCaseMediator is started again.
- secondLifecycle.stop();
- assertThat(secondController.getUseCaseMediator().isActive()).isFalse();
- assertThat(firstController.getUseCaseMediator().isActive()).isTrue();
- }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java
deleted file mode 100644
index 2dec264..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/UseCaseMediatorTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core.impl;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import androidx.camera.core.FakeOtherUseCase;
-import androidx.camera.core.FakeOtherUseCaseConfig;
-import androidx.camera.core.internal.CameraUseCaseAdapter;
-import androidx.camera.testing.fakes.FakeCamera;
-import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
-import androidx.camera.testing.fakes.FakeUseCase;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Collections;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class UseCaseMediatorTest {
- private final UseCaseMediator.StateChangeCallback mMockCallback =
- mock(UseCaseMediator.StateChangeCallback.class);
- private UseCaseMediator mUseCaseMediator;
- private FakeUseCase mFakeUseCase;
- private FakeOtherUseCase mFakeOtherUseCase;
- private CameraUseCaseAdapter mCameraUseCaseAdapter;
- private CameraInternal mMockCamera = mock(CameraInternal.class);
-
- @Before
- public void setUp() {
- FakeUseCaseConfig fakeUseCaseConfig = new FakeUseCaseConfig.Builder()
- .setTargetName("fakeUseCaseConfig")
- .getUseCaseConfig();
- FakeOtherUseCaseConfig fakeOtherUseCaseConfig =
- new FakeOtherUseCaseConfig.Builder()
- .setTargetName("fakeOtherUseCaseConfig")
- .getUseCaseConfig();
- mCameraUseCaseAdapter = new CameraUseCaseAdapter(new FakeCamera(),
- new FakeCameraDeviceSurfaceManager());
- mUseCaseMediator = new UseCaseMediator();
- mFakeUseCase = new FakeUseCase(fakeUseCaseConfig);
- mFakeOtherUseCase = new FakeOtherUseCase(fakeOtherUseCaseConfig);
- }
-
- @Test
- public void mediatorStartsEmpty() {
- assertThat(mUseCaseMediator.getUseCases()).isEmpty();
- }
-
- @Test
- public void newUseCaseIsAdded_whenNoneExistsInMediator() {
- assertThat(mUseCaseMediator.addUseCase(mFakeUseCase)).isTrue();
- assertThat(mUseCaseMediator.getUseCases()).containsExactly(mFakeUseCase);
- }
-
- @Test
- public void multipleUseCases_canBeAdded() {
- assertThat(mUseCaseMediator.addUseCase(mFakeUseCase)).isTrue();
- assertThat(mUseCaseMediator.addUseCase(mFakeOtherUseCase)).isTrue();
-
- assertThat(mUseCaseMediator.getUseCases()).containsExactly(mFakeUseCase, mFakeOtherUseCase);
- }
-
- @Test
- public void mediatorBecomesEmpty_afterMediatorIsCleared()
- throws CameraUseCaseAdapter.CameraException {
- mUseCaseMediator.addUseCase(mFakeUseCase);
- mCameraUseCaseAdapter.attachUseCases(Collections.singleton(mFakeUseCase));
-
- mUseCaseMediator.destroy();
-
- assertThat(mUseCaseMediator.getUseCases()).isEmpty();
- }
-
- @Test
- public void useCaseIsCleared_afterMediatorIsCleared()
- throws CameraUseCaseAdapter.CameraException {
- mUseCaseMediator.addUseCase(mFakeUseCase);
- mCameraUseCaseAdapter.attachUseCases(Collections.singleton(mFakeUseCase));
-
- assertThat(mFakeUseCase.isCleared()).isFalse();
-
- mUseCaseMediator.destroy();
-
- assertThat(mFakeUseCase.isCleared()).isTrue();
- }
-
- @Test
- public void useCaseRemoved_afterRemovedCalled() {
- mUseCaseMediator.addUseCase(mFakeUseCase);
-
- mUseCaseMediator.removeUseCase(mFakeUseCase);
-
- assertThat(mUseCaseMediator.getUseCases()).isEmpty();
- }
-
- @Test
- public void listenerOnMediatorActive_ifUseCaseMediatorStarted() {
- mUseCaseMediator.setListener(mMockCallback);
- mUseCaseMediator.start();
-
- verify(mMockCallback, times(1)).onActive(mUseCaseMediator);
- }
-
- @Test
- public void listenerOnMediatorInactive_ifUseCaseMediatorStopped() {
- mUseCaseMediator.setListener(mMockCallback);
- mUseCaseMediator.stop();
-
- verify(mMockCallback, times(1)).onInactive(mUseCaseMediator);
- }
-
- @Test
- public void setListener_replacesPreviousListener() {
- mUseCaseMediator.setListener(mMockCallback);
- mUseCaseMediator.setListener(null);
-
- mUseCaseMediator.start();
- verify(mMockCallback, never()).onActive(mUseCaseMediator);
- }
-}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java
index ba896c6..75bd8f0 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import androidx.camera.core.impl.CameraInternal;
import androidx.camera.testing.fakes.FakeCamera;
import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
import androidx.camera.testing.fakes.FakeUseCase;
@@ -29,6 +30,7 @@
import org.junit.runner.RunWith;
import java.util.Collections;
+import java.util.LinkedHashSet;
/** JUnit test cases for {@link CameraUseCaseAdapter} class. */
@SmallTest
@@ -36,31 +38,73 @@
public class CameraUseCaseAdapterTest {
FakeCameraDeviceSurfaceManager mFakeCameraDeviceSurfaceManager;
FakeCamera mFakeCamera;
+ LinkedHashSet<CameraInternal> mFakeCameraSet = new LinkedHashSet<>();
@Before
public void setUp() {
mFakeCameraDeviceSurfaceManager = new FakeCameraDeviceSurfaceManager();
- mFakeCamera = new FakeCamera();
+ mFakeCamera = new FakeCamera();
+ mFakeCameraSet.add(mFakeCamera);
}
@Test
public void attachUseCases() throws CameraUseCaseAdapter.CameraException {
CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ mFakeCameraSet,
mFakeCameraDeviceSurfaceManager);
FakeUseCase fakeUseCase = new FakeUseCase();
- cameraUseCaseAdapter.attachUseCases(Collections.singleton(fakeUseCase));
+ cameraUseCaseAdapter.addUseCases(Collections.singleton(fakeUseCase));
assertThat(fakeUseCase.getCamera()).isEqualTo(mFakeCamera);
+ assertThat(mFakeCamera.getAttachedUseCases()).containsExactly(fakeUseCase);
}
@Test
public void detachUseCases() throws CameraUseCaseAdapter.CameraException {
CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ mFakeCameraSet,
mFakeCameraDeviceSurfaceManager);
FakeUseCase fakeUseCase = new FakeUseCase();
- cameraUseCaseAdapter.attachUseCases(Collections.singleton(fakeUseCase));
- cameraUseCaseAdapter.detachUseCases(Collections.singleton(fakeUseCase));
+ cameraUseCaseAdapter.addUseCases(Collections.singleton(fakeUseCase));
+ cameraUseCaseAdapter.removeUseCases(Collections.singleton(fakeUseCase));
assertThat(fakeUseCase.getCamera()).isNull();
}
+
+ @Test
+ public void closeCameraUseCaseAdapter() throws CameraUseCaseAdapter.CameraException {
+ CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ mFakeCameraSet,
+ mFakeCameraDeviceSurfaceManager);
+ FakeUseCase fakeUseCase = new FakeUseCase();
+ cameraUseCaseAdapter.addUseCases(Collections.singleton(fakeUseCase));
+ cameraUseCaseAdapter.detachUseCases();
+
+ assertThat(fakeUseCase.getCamera()).isEqualTo(mFakeCamera);
+ assertThat(mFakeCamera.getAttachedUseCases()).isEmpty();
+ }
+
+ @Test
+ public void cameraIdEquals() {
+ CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ mFakeCameraSet,
+ mFakeCameraDeviceSurfaceManager);
+
+ CameraUseCaseAdapter.CameraId otherCameraId =
+ CameraUseCaseAdapter.generateCameraId(mFakeCameraSet);
+
+ assertThat(cameraUseCaseAdapter.getCameraId().equals(otherCameraId)).isTrue();
+ }
+
+ @Test
+ public void cameraEquivalent() {
+ CameraUseCaseAdapter cameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ mFakeCameraSet,
+ mFakeCameraDeviceSurfaceManager);
+
+ CameraUseCaseAdapter otherCameraUseCaseAdapter = new CameraUseCaseAdapter(mFakeCamera,
+ mFakeCameraSet,
+ mFakeCameraDeviceSurfaceManager);
+ assertThat(cameraUseCaseAdapter.isEquivalent(otherCameraUseCaseAdapter)).isTrue();
+ }
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
index 7b31439..71a7d11 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraSelector.java
@@ -71,6 +71,25 @@
@UseExperimental(markerClass = ExperimentalCameraFilter.class)
@NonNull
public CameraInternal select(@NonNull LinkedHashSet<CameraInternal> cameras) {
+ return filter(cameras).iterator().next();
+ }
+
+ /**
+ * Filters the input cameras using the {@link CameraFilter} assigned to the selector.
+ *
+ * <p>The camera filtered must be contained in the input set. Otherwise it will throw an
+ * exception.
+ *
+ * @param cameras The camera set being filtered.
+ * @return The remain set of cameras.
+ * @throws IllegalArgumentException If there's no available camera after being filtered or
+ * the filtered camera ids aren't contained in the input set.
+ * @hide
+ */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @UseExperimental(markerClass = ExperimentalCameraFilter.class)
+ @NonNull
+ public LinkedHashSet<CameraInternal> filter(@NonNull LinkedHashSet<CameraInternal> cameras) {
LinkedHashSet<Camera> camerasCopy = new LinkedHashSet<>(cameras);
LinkedHashSet<Camera> resultCameras = new LinkedHashSet<>(cameras);
for (CameraFilter filter : mCameraFilterSet) {
@@ -85,7 +104,12 @@
camerasCopy.retainAll(resultCameras);
}
- return (CameraInternal) resultCameras.iterator().next();
+ LinkedHashSet<CameraInternal> returnCameras = new LinkedHashSet<>();
+ for (Camera camera : resultCameras) {
+ returnCameras.add((CameraInternal) camera);
+ }
+
+ return returnCameras;
}
/**
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
index f73f4eb..739475c 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
@@ -19,12 +19,10 @@
import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Rect;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.util.Log;
-import android.util.Size;
import androidx.annotation.GuardedBy;
import androidx.annotation.MainThread;
@@ -39,17 +37,14 @@
import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.CameraRepository;
import androidx.camera.core.impl.CameraThreadConfig;
-import androidx.camera.core.impl.SurfaceConfig;
import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.impl.UseCaseConfigFactory;
-import androidx.camera.core.impl.UseCaseMediator;
import androidx.camera.core.impl.utils.Threads;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.core.impl.utils.futures.FutureCallback;
import androidx.camera.core.impl.utils.futures.FutureChain;
import androidx.camera.core.impl.utils.futures.Futures;
-import androidx.camera.core.internal.UseCaseOccupancy;
-import androidx.camera.core.internal.ViewPorts;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.core.os.HandlerCompat;
import androidx.core.util.Preconditions;
@@ -59,12 +54,10 @@
import com.google.common.util.concurrent.ListenableFuture;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -172,9 +165,10 @@
final CameraRepository mCameraRepository = new CameraRepository();
private final Object mInitializeLock = new Object();
- private final UseCaseMediatorRepository
- mUseCaseMediatorRepository = new UseCaseMediatorRepository();
+
private final CameraXConfig mCameraXConfig;
+ private final LifecycleCameraRepository
+ mLifecycleCameraRepository = new LifecycleCameraRepository();
private final Executor mCameraExecutor;
private final Handler mSchedulerHandler;
@Nullable
@@ -294,26 +288,8 @@
Threads.checkMainThread();
CameraX cameraX = checkInitialized();
// TODO(b/153096869): override UseCase's target rotation.
-
- UseCaseMediatorLifecycleController useCaseMediatorLifecycleController =
- cameraX.getOrCreateUseCaseMediator(lifecycleOwner);
- UseCaseMediator useCaseMediatorToBind =
- useCaseMediatorLifecycleController.getUseCaseMediator();
-
- Collection<UseCaseMediatorLifecycleController> controllers =
- cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
- for (UseCase useCase : useCases) {
- for (UseCaseMediatorLifecycleController controller : controllers) {
- UseCaseMediator useCaseMediator = controller.getUseCaseMediator();
- if (useCaseMediator.contains(useCase) && useCaseMediator != useCaseMediatorToBind) {
- throw new IllegalStateException(
- String.format(
- "Use case %s already bound to a different lifecycle.",
- useCase));
- }
- }
- }
-
+ // TODO(b/154939118) The filter appending should be removed after extensions are moved to
+ // the CheckedCameraInternal
CameraSelector.Builder selectorBuilder =
CameraSelector.Builder.fromSelector(cameraSelector);
// Append the camera filter required internally if there's any.
@@ -326,68 +302,53 @@
}
}
- // Try to get the camera before binding to the use case, and throw IllegalArgumentException
- // if the camera not found.
- CameraInternal camera = CameraX.getCameraWithCameraSelector(selectorBuilder.build());
+ CameraSelector modifiedSelector = selectorBuilder.build();
- if (useCases.length == 0) {
- return camera;
- }
+ LinkedHashSet<CameraInternal> cameraInternals =
+ modifiedSelector.filter(cameraX.mCameraRepository.getCameras());
+ CameraUseCaseAdapter.CameraId cameraId =
+ CameraUseCaseAdapter.generateCameraId(cameraInternals);
- List<UseCase> originalUseCases = new ArrayList<>();
+ LifecycleCamera lifecycleCameraToBind =
+ cameraX.mLifecycleCameraRepository.getLifecycleCamera(lifecycleOwner, cameraId);
- // Collect original use cases attached to the camera
- for (UseCase useCase : useCaseMediatorToBind.getUseCases()) {
- CameraInternal attachedCamera = useCase.getCamera();
- if (attachedCamera != null) {
- if (camera.equals(attachedCamera)) {
- originalUseCases.add(useCase);
+ Collection<LifecycleCamera> lifecycleCameras =
+ cameraX.mLifecycleCameraRepository.getLifecycleCameras();
+ for (UseCase useCase : useCases) {
+ for (LifecycleCamera lifecycleCamera : lifecycleCameras) {
+ if (lifecycleCamera.isBound(useCase)
+ && lifecycleCamera != lifecycleCameraToBind) {
+ throw new IllegalStateException(
+ String.format(
+ "Use case %s already bound to a different lifecycle.",
+ useCase));
}
}
}
- // Only do resolution calculation if UseCases were attached
- List<UseCase> totalUseCases = new ArrayList<>(originalUseCases);
- totalUseCases.addAll(Arrays.asList(useCases));
- if (!UseCaseOccupancy.checkUseCaseLimitNotExceeded(totalUseCases)) {
- throw new IllegalArgumentException("Attempting to bind too many ImageCapture or "
- + "VideoCapture instances");
+ // Try to get the camera before binding to the use case, and throw IllegalArgumentException
+ // if the camera not found.
+ if (lifecycleCameraToBind == null) {
+ lifecycleCameraToBind =
+ cameraX.mLifecycleCameraRepository.createLifecycleCamera(lifecycleOwner,
+ new CameraUseCaseAdapter(cameraInternals.iterator().next(),
+ cameraInternals,
+ cameraX.getCameraDeviceSurfaceManager()));
}
- Map<UseCase, Size> suggestedResolutionsMap = calculateSuggestedResolutions(
- camera.getCameraInfoInternal(),
- originalUseCases,
- Arrays.asList(useCases));
- if (viewPort != null) {
- // Calculate crop rect if view port is provided.
- Map<UseCase, Rect> cropRectMap = ViewPorts.calculateViewPortRects(
- camera.getCameraControlInternal().getSensorRect(),
- viewPort.getAspectRatio(),
- camera.getCameraInfoInternal().getSensorRotationDegrees(
- viewPort.getRotation()),
- viewPort.getScaleType(),
- viewPort.getLayoutDirection(),
- suggestedResolutionsMap);
- for (UseCase useCase : useCases) {
- useCase.setViewPortCropRect(cropRectMap.get(useCase));
- }
+ if (useCases.length == 0) {
+ return lifecycleCameraToBind;
}
- // At this point the binding will succeed since all the calculations are done
- // Do all binding related work
- for (UseCase useCase : useCases) {
- useCase.onAttach(camera);
- useCase.updateSuggestedResolution(
- Preconditions.checkNotNull(suggestedResolutionsMap.get(useCase)));
-
- // Update the UseCaseMediator
- useCaseMediatorToBind.addUseCase(useCase);
+ try {
+ lifecycleCameraToBind.getCameraUseCaseAdapter().setViewPort(viewPort);
+ lifecycleCameraToBind.bind(Arrays.asList(useCases));
+ } catch (CameraUseCaseAdapter.CameraException e) {
+ throw new IllegalArgumentException(e.getMessage());
}
- useCaseMediatorLifecycleController.notifyState();
-
- return camera;
+ return lifecycleCameraToBind;
}
/**
@@ -403,12 +364,9 @@
public static boolean isBound(@NonNull UseCase useCase) {
CameraX cameraX = checkInitialized();
- Collection<UseCaseMediatorLifecycleController> controllers =
- cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-
- for (UseCaseMediatorLifecycleController controller : controllers) {
- UseCaseMediator useCaseMediator = controller.getUseCaseMediator();
- if (useCaseMediator.contains(useCase)) {
+ for (LifecycleCamera lifecycleCamera :
+ cameraX.mLifecycleCameraRepository.getLifecycleCameras()) {
+ if (lifecycleCamera.isBound(useCase)) {
return true;
}
}
@@ -436,26 +394,9 @@
Threads.checkMainThread();
CameraX cameraX = checkInitialized();
- Collection<UseCaseMediatorLifecycleController> useCaseMediators =
- cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-
- for (UseCase useCase : useCases) {
- // Remove the UseCase from the mediator.
- boolean wasUnbound = false;
- for (UseCaseMediatorLifecycleController useCaseMediatorLifecycleController :
- useCaseMediators) {
- if (useCaseMediatorLifecycleController.getUseCaseMediator().removeUseCase(
- useCase)) {
- wasUnbound = true;
- }
- }
-
- // Unbind the UseCase from the currently bound camera if it is bound
- CameraInternal attachedCamera = useCase.getCamera();
- if (wasUnbound && attachedCamera != null) {
- useCase.onDetach(attachedCamera);
- useCase.onDestroy();
- }
+ for (LifecycleCamera lifecycleCamera :
+ cameraX.mLifecycleCameraRepository.getLifecycleCameras()) {
+ lifecycleCamera.unbind(Arrays.asList(useCases));
}
}
@@ -472,18 +413,10 @@
Threads.checkMainThread();
CameraX cameraX = checkInitialized();
- Collection<UseCaseMediatorLifecycleController> useCaseMediators =
- cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
-
- List<UseCase> useCases = new ArrayList<>();
- for (UseCaseMediatorLifecycleController useCaseMediatorLifecycleController :
- useCaseMediators) {
- UseCaseMediator useCaseMediator =
- useCaseMediatorLifecycleController.getUseCaseMediator();
- useCases.addAll(useCaseMediator.getUseCases());
+ for (LifecycleCamera lifecycleCamera :
+ cameraX.mLifecycleCameraRepository.getLifecycleCameras()) {
+ lifecycleCamera.unbindAll();
}
-
- unbind(useCases.toArray(new UseCase[0]));
}
/**
@@ -771,12 +704,12 @@
Collection<UseCase> activeUseCases = null;
- Collection<UseCaseMediatorLifecycleController> controllers =
- cameraX.mUseCaseMediatorRepository.getUseCaseMediators();
+ Collection<LifecycleCamera> lifecycleCameras =
+ cameraX.mLifecycleCameraRepository.getLifecycleCameras();
- for (UseCaseMediatorLifecycleController controller : controllers) {
- if (controller.getUseCaseMediator().isActive()) {
- activeUseCases = controller.getUseCaseMediator().getUseCases();
+ for (LifecycleCamera lifecycleCamera : lifecycleCameras) {
+ if (lifecycleCamera.isActive()) {
+ activeUseCases = lifecycleCamera.getUseCases();
break;
}
}
@@ -935,45 +868,6 @@
}
- private static Map<UseCase, Size> calculateSuggestedResolutions(
- @NonNull CameraInfoInternal cameraInfo,
- @NonNull List<UseCase> originalUseCases, @NonNull List<UseCase> newUseCases) {
- List<SurfaceConfig> existingSurfaces = new ArrayList<>();
- String cameraId = cameraInfo.getCameraId();
-
- // Collect original use cases for different camera devices
- for (UseCase useCase : originalUseCases) {
- SurfaceConfig surfaceConfig =
- getSurfaceManager().transformSurfaceConfig(cameraId,
- useCase.getImageFormat(),
- useCase.getAttachedSurfaceResolution());
- existingSurfaces.add(surfaceConfig);
- }
-
- Map<UseCaseConfig<?>, UseCase> configToUseCaseMap = new HashMap<>();
- for (UseCase useCase : newUseCases) {
- UseCaseConfig.Builder<?, ?, ?> defaultBuilder = useCase.getDefaultBuilder(cameraInfo);
-
- // Combine with default configuration.
- UseCaseConfig<?> combinedUseCaseConfig =
- useCase.applyDefaults(useCase.getUseCaseConfig(),
- defaultBuilder);
- configToUseCaseMap.put(combinedUseCaseConfig, useCase);
- }
-
- // Get suggested resolutions and update the use case session configuration
- Map<UseCaseConfig<?>, Size> useCaseConfigSizeMap = getSurfaceManager()
- .getSuggestedResolutions(cameraId, existingSurfaces,
- new ArrayList<>(configToUseCaseMap.keySet()));
-
- Map<UseCase, Size> suggestedResolutions = new HashMap<>();
- for (Map.Entry<UseCaseConfig<?>, UseCase> entry : configToUseCaseMap.entrySet()) {
- suggestedResolutions.put(entry.getValue(), useCaseConfigSizeMap.get(entry.getKey()));
- }
-
- return suggestedResolutions;
- }
-
/**
* Returns the {@link CameraDeviceSurfaceManager} instance.
*
@@ -1121,12 +1015,6 @@
}
}
- private UseCaseMediatorLifecycleController getOrCreateUseCaseMediator(
- LifecycleOwner lifecycleOwner) {
- return mUseCaseMediatorRepository.getOrCreateUseCaseMediator(
- lifecycleOwner, useCaseMediator -> useCaseMediator.setListener(mCameraRepository));
- }
-
private CameraRepository getCameraRepository() {
return mCameraRepository;
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCamera.java b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCamera.java
new file mode 100644
index 0000000..28bc9bf
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCamera.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.Lifecycle.State;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A {@link CameraUseCaseAdapter} whose starting and stopping is controlled by a
+ * {@link Lifecycle}.
+ */
+final class LifecycleCamera implements LifecycleObserver, Camera {
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ // The lifecycle that controls the LifecycleCamera
+ private final LifecycleOwner mLifecycleOwner;
+
+ private final CameraUseCaseAdapter mCameraUseCaseAdapter;
+
+ @GuardedBy("mLock")
+ private volatile boolean mIsActive = false;
+
+ @GuardedBy("mLock")
+ private boolean mSuspended = false;
+
+ @GuardedBy("mLock")
+ private boolean mReleased = false;
+
+ /**
+ * Wraps an existing {@link CameraUseCaseAdapter} so it is controlled by lifecycle transitions.
+ */
+ LifecycleCamera(LifecycleOwner lifecycleOwner, CameraUseCaseAdapter cameraUseCaseAdaptor) {
+ mLifecycleOwner = lifecycleOwner;
+ mCameraUseCaseAdapter = cameraUseCaseAdaptor;
+ lifecycleOwner.getLifecycle().addObserver(this);
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart(LifecycleOwner lifecycleOwner) {
+ synchronized (mLock) {
+ if (!mSuspended && !mReleased) {
+ mCameraUseCaseAdapter.attachUseCases();
+ mIsActive = true;
+ }
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop(LifecycleOwner lifecycleOwner) {
+ synchronized (mLock) {
+ if (!mSuspended && !mReleased) {
+ mCameraUseCaseAdapter.detachUseCases();
+ mIsActive = false;
+ }
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ public void onDestroy(LifecycleOwner lifecycleOwner) {
+ synchronized (mLock) {
+ mCameraUseCaseAdapter.removeUseCases(mCameraUseCaseAdapter.getUseCases());
+ }
+ }
+
+ /**
+ * Suspend the camera so that it ignore lifecycle events.
+ *
+ * <p> This will also close the {@link CameraUseCaseAdapter}.
+ *
+ * <p> This will be idempotent if the camera is already suspended.
+ */
+ public void suspend() {
+ synchronized (mLock) {
+ if (mSuspended) {
+ return;
+ }
+
+ onStop(mLifecycleOwner);
+ mSuspended = true;
+ }
+ }
+
+ /**
+ * Unsuspend the camera so it will start listening to lifecycle events.
+ *
+ * <p> This will also open the {@link CameraUseCaseAdapter} if the lifecycle is in a STARTED
+ * state or above.
+ *
+ * <p> This will be idempotent if the camera is already in an unsuspended state.
+ */
+ public void unsuspend() {
+ synchronized (mLock) {
+ if (!mSuspended) {
+ return;
+ }
+
+ mSuspended = false;
+ if (mLifecycleOwner.getLifecycle().getCurrentState().isAtLeast(State.STARTED)) {
+ onStart(mLifecycleOwner);
+ }
+ }
+ }
+
+ // TODO(b/154939118) remove when Extension.setExtension() is implemented since there no
+ // longer is a need to check if the camera is active.
+ public boolean isActive() {
+ synchronized (mLock) {
+ return mIsActive;
+ }
+ }
+
+ public boolean isBound(@NonNull UseCase useCase) {
+ synchronized (mLock) {
+ return mCameraUseCaseAdapter.getUseCases().contains(useCase);
+ }
+ }
+
+ @NonNull
+ public List<UseCase> getUseCases() {
+ synchronized (mLock) {
+ return Collections.unmodifiableList(mCameraUseCaseAdapter.getUseCases());
+ }
+ }
+
+ public CameraUseCaseAdapter getCameraUseCaseAdapter() {
+ return mCameraUseCaseAdapter;
+ }
+
+ /**
+ * Bind the UseCases to the lifecycle camera.
+ *
+ * <>This will attach the UseCases to the CameraUseCaseAdapter if successful.
+ *
+ * @throws CameraUseCaseAdapter.CameraException if unable to attach the UseCase to the camera.
+ */
+ void bind(Collection<UseCase> useCases) throws CameraUseCaseAdapter.CameraException {
+ synchronized (mLock) {
+ mCameraUseCaseAdapter.addUseCases(useCases);
+ for (UseCase useCase : useCases) {
+ useCase.notifyState();
+ }
+ }
+ }
+
+ /**
+ * Unbind the UseCases from the lifecycle camera.
+ *
+ * <>This will detach the UseCases from the CameraUseCaseAdapter.
+ */
+ void unbind(Collection<UseCase> useCases) {
+ synchronized (mLock) {
+ mCameraUseCaseAdapter.removeUseCases(useCases);
+ }
+ }
+
+ /**
+ * Unbind all of the UseCases from the lifecycle camera.
+ *
+ * <p>This will detach all UseCases from the CameraUseCaseAdapter.
+ */
+ void unbindAll() {
+ synchronized (mLock) {
+ mCameraUseCaseAdapter.removeUseCases(mCameraUseCaseAdapter.getUseCases());
+ }
+ }
+
+ /**
+ * Stops observing lifecycle changes.
+ *
+ * <p>Once released the wrapped {@link LifecycleCamera} is still valid, but will no longer be
+ * triggered by lifecycle state transitions. In order to observe lifecycle changes again a new
+ * {@link LifecycleCamera} instance should be created.
+ *
+ * <p>Calls subsequent to the first time will do nothing.
+ */
+ void release() {
+ synchronized (mLock) {
+ mReleased = true;
+ mIsActive = false;
+ mLifecycleOwner.getLifecycle().removeObserver(this);
+ }
+ }
+
+ @NonNull
+ @Override
+ public CameraControl getCameraControl() {
+ return mCameraUseCaseAdapter.getCameraControlInternal();
+ }
+
+ @NonNull
+ @Override
+ public CameraInfo getCameraInfo() {
+ return mCameraUseCaseAdapter.getCameraInfoInternal();
+ }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCameraRepository.java b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCameraRepository.java
new file mode 100644
index 0000000..7b155ee
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LifecycleCameraRepository.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.camera.core.impl.CameraInternal;
+import androidx.camera.core.internal.CameraUseCaseAdapter;
+import androidx.core.util.Preconditions;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.Lifecycle.State;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import com.google.auto.value.AutoValue;
+
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A repository of {@link LifecycleCamera} instances.
+ *
+ * <p> This repository maps each unique pair of {@link LifecycleOwner} and set of
+ * {@link CameraInternal} to a single LifecycleCamera.
+ *
+ * <p> The repository ensures that only a single LifecycleCamera is active at a time so if the
+ * Lifecycle of a camera starts then it will take over as the current active camera. This means
+ * that at anytime only one of the LifecycleCamera in the repo will be in the unsuspended state.
+ * All others will be suspended.
+ *
+ * <p> When the Lifecycle of the most recently active camera stops then it will make sure
+ * that the next most recently started camera become the active camera.
+ *
+ * <p> A LifecycleCamera associated with the repository can also be released from the repository.
+ * When it is released, all UseCases bound to the LifecycleCamera will be unbound and the
+ * LifecycleCamera will be released.
+ */
+final class LifecycleCameraRepository {
+ final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ final Map<Key, LifecycleCamera> mCameraMap = new HashMap<>();
+
+ @GuardedBy("mLock")
+ final Map<Key, LifecycleCameraRepositoryObserver> mLifecycleObserverMap = new HashMap<>();
+
+ @GuardedBy("mLock")
+ private final ArrayDeque<Key> mActiveCameras = new ArrayDeque<>();
+
+ /**
+ * Create a new {@link LifecycleCamera} associated with the given {@link LifecycleOwner}.
+ *
+ * <p>The {@link LifecycleCamera} is set to be an observer of the {@link
+ * LifecycleOwner}.
+ *
+ * @param lifecycleOwner to associate with the LifecycleCamera
+ * @param cameraUseCaseAdaptor the CameraUseCaseAdapter to wrap in a LifecycleCamera
+ *
+ * @throws IllegalArgumentException if the LifecycleOwner is already in a destroyed state or
+ * if the repository already contains a LifecycleCamera that has the same LifecycleOwner and
+ * CameraInternal set as the CameraUseCaseAdapter.
+ */
+ LifecycleCamera createLifecycleCamera(
+ @NonNull LifecycleOwner lifecycleOwner,
+ @NonNull CameraUseCaseAdapter cameraUseCaseAdaptor) {
+ LifecycleCamera lifecycleCamera;
+ synchronized (mLock) {
+ Key key = Key.create(lifecycleOwner, cameraUseCaseAdaptor.getCameraId());
+ Preconditions.checkArgument(mCameraMap.get(key) == null, "LifecycleCamera already "
+ + "exists for the given LifecycleOwner and set of cameras");
+
+ if (lifecycleOwner.getLifecycle().getCurrentState() == State.DESTROYED) {
+ throw new IllegalArgumentException(
+ "Trying to create LifecycleCamera with destroyed lifecycle.");
+ }
+
+ // Need to add observer before creating LifecycleCamera to make sure
+ // it can be stopped before the latest active one is started.'
+ lifecycleCamera = new LifecycleCamera(lifecycleOwner, cameraUseCaseAdaptor);
+ registerCamera(key, lifecycleCamera);
+ }
+ return lifecycleCamera;
+ }
+
+ /**
+ * Get the LifecycleCamera which contains the same LifecycleOwner and a
+ * CameraUseCaseAdapter.CameraId.
+ *
+ * @return null if no such LifecycleCamera exists.
+ */
+ @Nullable
+ LifecycleCamera getLifecycleCamera(LifecycleOwner lifecycleOwner,
+ CameraUseCaseAdapter.CameraId cameraId) {
+ synchronized (mLock) {
+ return mCameraMap.get(Key.create(lifecycleOwner, cameraId));
+ }
+ }
+
+ /**
+ * Returns all the LifecycleCamera that have been created by the repository which haven't
+ * been destroyed yet.
+ */
+ Collection<LifecycleCamera> getLifecycleCameras() {
+ synchronized (mLock) {
+ return Collections.unmodifiableCollection(mCameraMap.values());
+ }
+ }
+
+ // Registers the LifecycleCamera in the repository so that the repository ensures that only one
+ // camera is active at one time.
+ private void registerCamera(Key key, LifecycleCamera lifecycleCamera) {
+ synchronized (mLock) {
+ LifecycleCameraRepositoryObserver observer =
+ new LifecycleCameraRepositoryObserver(key, this);
+ mLifecycleObserverMap.put(key, observer);
+ mCameraMap.put(key, lifecycleCamera);
+ key.getLifecycleOwner().getLifecycle().addObserver(observer);
+ }
+ }
+
+ // Unregisters the Lifecycle from the repository so it is no longer tracked by the repository.
+ // This does not stop the camera from receiving its lifecycle events. For the LifecycleCamera
+ // to stop receiving lifecycle event it must be done manually either before or after.
+ void unregisterCamera(Key key) {
+ synchronized (mLock) {
+ setInactive(key);
+ mCameraMap.remove(key);
+ LifecycleCameraRepositoryObserver observer = mLifecycleObserverMap.remove(key);
+ if (observer != null) {
+ key.getLifecycleOwner().getLifecycle().removeObserver(observer);
+ }
+
+ }
+ }
+
+ // Sets the LifecycleCamera with the associated key as the current active camera. This will
+ // suspend all other cameras which are tracked by the repository.
+ void setActive(Key key) {
+ synchronized (mLock) {
+ LifecycleCamera camera = mCameraMap.get(key);
+ if (camera != null) {
+
+ // Only keep the last {@link LifecycleOwner} active. Stop the others.
+ if (mActiveCameras.isEmpty()) {
+ mActiveCameras.push(key);
+ } else {
+ Key currentActiveCamera = mActiveCameras.peek();
+ if (currentActiveCamera != key) {
+ Preconditions.checkNotNull(
+ mCameraMap.get(currentActiveCamera)).suspend();
+ mActiveCameras.push(key);
+ }
+ }
+ camera.unsuspend();
+ }
+ }
+ }
+
+ // Removes the LifecycleCamera with the associated key from list of active cameras.
+ // If this camera was the current active camera then the next most recently active camera in
+ // the current active list will become the active camera.
+ void setInactive(Key key) {
+ synchronized (mLock) {
+ // Removes stopped lifecycleOwner from active list.
+ mActiveCameras.remove(key);
+
+ // Start up next LifecycleCamera if there are still active cameras
+ if (!mActiveCameras.isEmpty()) {
+ Preconditions.checkNotNull(
+ mCameraMap.get(mActiveCameras.peek())).unsuspend();
+ }
+ }
+ }
+
+ /**
+ * A key for mapping a {@link LifecycleOwner} and set of {@link CameraInternal} to a
+ * {@link LifecycleCamera}.
+ */
+ @AutoValue
+ abstract static class Key {
+ static Key create(@NonNull LifecycleOwner lifecycleOwner,
+ @NonNull CameraUseCaseAdapter.CameraId cameraId) {
+ return new AutoValue_LifecycleCameraRepository_Key(lifecycleOwner, cameraId);
+ }
+
+ @NonNull
+ public abstract LifecycleOwner getLifecycleOwner();
+
+ @NonNull
+ public abstract CameraUseCaseAdapter.CameraId getCameraId();
+ }
+
+ private static class LifecycleCameraRepositoryObserver implements LifecycleObserver {
+ private final LifecycleCameraRepository mLifecycleCameraRepository;
+ private final Key mKey;
+
+ LifecycleCameraRepositoryObserver(Key key,
+ LifecycleCameraRepository lifecycleCameraRepository) {
+ mKey = key;
+ mLifecycleCameraRepository = lifecycleCameraRepository;
+ }
+
+ /**
+ * Monitors which {@link LifecycleOwner} receives an ON_START event and then stop
+ * other {@link LifecycleCamera} to keep only one active at a time.
+ */
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart(LifecycleOwner lifecycleOwner) {
+ mLifecycleCameraRepository.setActive(mKey);
+ }
+
+ /**
+ * Monitors which {@link LifecycleOwner} receives an ON_STOP event.
+ */
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop(LifecycleOwner lifecycleOwner) {
+ mLifecycleCameraRepository.setInactive(mKey);
+ }
+
+ /**
+ * Monitors which {@link LifecycleOwner} receives an ON_DESTROY event and then
+ * removes any {@link LifecycleCamera} associated with it from this
+ * repository when that lifecycle is destroyed.
+ */
+ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ public void onDestroy(LifecycleOwner lifecycleOwner) {
+ mLifecycleCameraRepository.unregisterCamera(mKey);
+ }
+ }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
index 7bff94e..a49dbb0 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/UseCase.java
@@ -127,7 +127,7 @@
protected final void updateUseCaseConfig(@NonNull UseCaseConfig<?> useCaseConfig) {
// Attempt to retrieve builder containing defaults for this use case's config
UseCaseConfig.Builder<?, ?, ?> defaultBuilder =
- getDefaultBuilder(getCamera() == null ? null : getCamera().getCameraInfo());
+ getDefaultBuilder(getCamera() == null ? null : getCamera().getCameraInfoInternal());
// Combine with default configuration.
mUseCaseConfig = applyDefaults(useCaseConfig, defaultBuilder);
@@ -428,6 +428,7 @@
*/
@RestrictTo(Scope.LIBRARY_GROUP)
public void onAttach(@NonNull CameraInternal camera) {
+
synchronized (mCameraLock) {
mCamera = camera;
addStateChangeCallback(camera);
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorLifecycleController.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorLifecycleController.java
deleted file mode 100644
index b1b860a..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorLifecycleController.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import androidx.annotation.GuardedBy;
-import androidx.camera.core.impl.UseCaseMediator;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-
-/** A {@link UseCaseMediator} whose starting and stopping is controlled by a {@link Lifecycle}. */
-final class UseCaseMediatorLifecycleController implements LifecycleObserver {
- private final Object mUseCaseMediatorLock = new Object();
-
- @GuardedBy("mUseCaseMediatorLock")
- private final UseCaseMediator mUseCaseMediator;
-
- /** The lifecycle that controls the {@link UseCaseMediator}. */
- private final Lifecycle mLifecycle;
-
- /** Creates a new {@link UseCaseMediator} which gets controlled by lifecycle transitions. */
- UseCaseMediatorLifecycleController(Lifecycle lifecycle) {
- this(lifecycle, new UseCaseMediator());
- }
-
- /** Wraps an existing {@link UseCaseMediator} so it is controlled by lifecycle transitions. */
- UseCaseMediatorLifecycleController(Lifecycle lifecycle, UseCaseMediator useCaseMediator) {
- this.mUseCaseMediator = useCaseMediator;
- this.mLifecycle = lifecycle;
- lifecycle.addObserver(this);
- }
-
- @OnLifecycleEvent(Lifecycle.Event.ON_START)
- public void onStart(LifecycleOwner lifecycleOwner) {
- synchronized (mUseCaseMediatorLock) {
- mUseCaseMediator.start();
- }
- }
-
- @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
- public void onStop(LifecycleOwner lifecycleOwner) {
- synchronized (mUseCaseMediatorLock) {
- mUseCaseMediator.stop();
- }
- }
-
- @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
- public void onDestroy(LifecycleOwner lifecycleOwner) {
- synchronized (mUseCaseMediatorLock) {
- mUseCaseMediator.destroy();
- }
- }
-
- /**
- * Starts the underlying {@link UseCaseMediator} so that its {@link
- * UseCaseMediator.StateChangeCallback} can be notified.
- *
- * <p>This is required when the contained {@link Lifecycle} is in a STARTED state, since the
- * default state for a {@link UseCaseMediator} is inactive. The explicit call forces a check on
- * the actual state of the mediator.
- */
- void notifyState() {
- synchronized (mUseCaseMediatorLock) {
- if (mLifecycle.getCurrentState().isAtLeast(State.STARTED)) {
- mUseCaseMediator.start();
- }
- for (UseCase useCase : mUseCaseMediator.getUseCases()) {
- useCase.notifyState();
- }
- }
- }
-
- UseCaseMediator getUseCaseMediator() {
- synchronized (mUseCaseMediatorLock) {
- return mUseCaseMediator;
- }
- }
-
- /**
- * Stops observing lifecycle changes.
- *
- * <p>Once released the wrapped {@link UseCaseMediator} is still valid, but will no longer be
- * triggered by lifecycle state transitions. In order to observe lifecycle changes again a new
- * {@link UseCaseMediatorLifecycleController} instance should be created.
- *
- * <p>Calls subsequent to the first time will do nothing.
- */
- void release() {
- mLifecycle.removeObserver(this);
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorRepository.java b/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorRepository.java
deleted file mode 100644
index c47c40f..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/UseCaseMediatorRepository.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.camera.core.impl.UseCaseMediator;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A repository of {@link UseCaseMediatorLifecycleController} instances.
- *
- * <p>Each {@link UseCaseMediatorLifecycleController} is associated with a {@link LifecycleOwner}
- * that regulates the common lifecycle shared by all the use cases in the mediator.
- */
-final class UseCaseMediatorRepository {
- final Object mUseCasesLock = new Object();
-
- @GuardedBy("mUseCasesLock")
- final Map<LifecycleOwner, UseCaseMediatorLifecycleController>
- mLifecycleToUseCaseMediatorControllerMap =
- new HashMap<>();
- @GuardedBy("mUseCasesLock")
- final List<LifecycleOwner> mActiveLifecycleOwnerList = new ArrayList<>();
- @GuardedBy("mUseCasesLock")
- LifecycleOwner mCurrentActiveLifecycleOwner = null;
-
- /**
- * Gets an existing {@link UseCaseMediatorLifecycleController} associated with the given {@link
- * LifecycleOwner}, or creates a new {@link UseCaseMediatorLifecycleController} if a mediator
- * does not already exist.
- *
- * <p>The {@link UseCaseMediatorLifecycleController} is set to be an observer of the {@link
- * LifecycleOwner}.
- *
- * @param lifecycleOwner to associate with the mediator
- */
- UseCaseMediatorLifecycleController getOrCreateUseCaseMediator(LifecycleOwner lifecycleOwner) {
- return getOrCreateUseCaseMediator(lifecycleOwner, useCaseMediator -> {
- });
- }
-
- /**
- * Gets an existing {@link UseCaseMediatorLifecycleController} associated with the given {@link
- * LifecycleOwner}, or creates a new {@link UseCaseMediatorLifecycleController} if a mediator
- * does not already exist.
- *
- * <p>The {@link UseCaseMediatorLifecycleController} is set to be an observer of the {@link
- * LifecycleOwner}.
- *
- * @param lifecycleOwner to associate with the mediator
- * @param mediatorSetup additional setup to do on the mediator if a new instance is created
- */
- UseCaseMediatorLifecycleController getOrCreateUseCaseMediator(
- LifecycleOwner lifecycleOwner, UseCaseMediatorSetup mediatorSetup) {
- UseCaseMediatorLifecycleController useCaseMediatorLifecycleController;
- synchronized (mUseCasesLock) {
- useCaseMediatorLifecycleController = mLifecycleToUseCaseMediatorControllerMap.get(
- lifecycleOwner);
- if (useCaseMediatorLifecycleController == null) {
- useCaseMediatorLifecycleController = createUseCaseMediator(lifecycleOwner);
- mediatorSetup.setup(useCaseMediatorLifecycleController.getUseCaseMediator());
- }
- }
- return useCaseMediatorLifecycleController;
- }
-
- /**
- * Creates a new {@link UseCaseMediatorLifecycleController} associated with the given {@link
- * LifecycleOwner} and adds the mediator to the repository.
- *
- * <p>The {@link UseCaseMediatorLifecycleController} is set to be an observer of the {@link
- * LifecycleOwner}.
- *
- * @param lifecycleOwner to associate with the mediator
- * @return a new {@link UseCaseMediatorLifecycleController}
- * @throws IllegalArgumentException if the {@link androidx.lifecycle.Lifecycle} of
- * lifecycleOwner is already
- * {@link androidx.lifecycle.Lifecycle.State.DESTROYED}.
- */
- private UseCaseMediatorLifecycleController createUseCaseMediator(
- LifecycleOwner lifecycleOwner) {
- if (lifecycleOwner.getLifecycle().getCurrentState() == State.DESTROYED) {
- throw new IllegalArgumentException(
- "Trying to create use case mediator with destroyed lifecycle.");
- }
-
- // Need to add observer before creating UseCaseMediatorLifecycleController to make sure
- // UseCaseMediators can be stopped before the latest active one is started.
- lifecycleOwner.getLifecycle().addObserver(createLifecycleObserver());
- UseCaseMediatorLifecycleController useCaseMediatorLifecycleController =
- new UseCaseMediatorLifecycleController(lifecycleOwner.getLifecycle());
- synchronized (mUseCasesLock) {
- mLifecycleToUseCaseMediatorControllerMap.put(lifecycleOwner,
- useCaseMediatorLifecycleController);
- }
- return useCaseMediatorLifecycleController;
- }
-
- /**
- * Creates a {@link LifecycleObserver} to monitor state change of {@link LifecycleOwner}.
- *
- * @return a new {@link LifecycleObserver}
- */
- private LifecycleObserver createLifecycleObserver() {
- return new LifecycleObserver() {
- /**
- * Monitors which {@link LifecycleOwner} receives an ON_START event and then stop
- * others {@link UseCaseMediator} to keep only one active at a time.
- */
- @OnLifecycleEvent(Lifecycle.Event.ON_START)
- public void onStart(LifecycleOwner lifecycleOwner) {
- synchronized (mUseCasesLock) {
- // Only keep the last {@link LifecycleOwner} active. Stop the others.
- for (Map.Entry<LifecycleOwner, UseCaseMediatorLifecycleController> entry :
- mLifecycleToUseCaseMediatorControllerMap.entrySet()) {
- if (entry.getKey() != lifecycleOwner) {
- UseCaseMediator useCaseMediator = entry.getValue().getUseCaseMediator();
- if (useCaseMediator.isActive()) {
- useCaseMediator.stop();
- }
- }
- }
-
- mCurrentActiveLifecycleOwner = lifecycleOwner;
- mActiveLifecycleOwnerList.add(0, mCurrentActiveLifecycleOwner);
- }
- }
-
- /**
- * Monitors which {@link LifecycleOwner} receives an ON_STOP event.
- */
- @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
- public void onStop(LifecycleOwner lifecycleOwner) {
- synchronized (mUseCasesLock) {
- // Removes stopped lifecycleOwner from active list.
- mActiveLifecycleOwnerList.remove(lifecycleOwner);
- if (mCurrentActiveLifecycleOwner == lifecycleOwner) {
- // If stopped lifecycleOwner is original active one, check whether there
- // is other active lifecycleOwner and start UseCaseMediator belong to it.
- if (mActiveLifecycleOwnerList.size() > 0) {
- mCurrentActiveLifecycleOwner = mActiveLifecycleOwnerList.get(0);
- mLifecycleToUseCaseMediatorControllerMap.get(
- mCurrentActiveLifecycleOwner).getUseCaseMediator().start();
- } else {
- mCurrentActiveLifecycleOwner = null;
- }
- }
- }
- }
-
- /**
- * Monitors which {@link LifecycleOwner} receives an ON_DESTROY event and then
- * removes any {@link UseCaseMediatorLifecycleController} associated with it from this
- * repository when that lifecycle is destroyed.
- */
- @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
- public void onDestroy(LifecycleOwner lifecycleOwner) {
- synchronized (mUseCasesLock) {
- mLifecycleToUseCaseMediatorControllerMap.remove(lifecycleOwner);
- }
- lifecycleOwner.getLifecycle().removeObserver(this);
- }
- };
- }
-
- Collection<UseCaseMediatorLifecycleController> getUseCaseMediators() {
- synchronized (mUseCasesLock) {
- return Collections.unmodifiableCollection(
- mLifecycleToUseCaseMediatorControllerMap.values());
- }
- }
-
- @VisibleForTesting
- Map<LifecycleOwner, UseCaseMediatorLifecycleController> getUseCasesMap() {
- synchronized (mUseCasesLock) {
- return mLifecycleToUseCaseMediatorControllerMap;
- }
- }
-
- /**
- * The interface for doing additional setup work on a newly created {@link UseCaseMediator}
- * instance.
- */
- public interface UseCaseMediatorSetup {
- void setup(@NonNull UseCaseMediator useCaseMediator);
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
index 25ccb0d..eb1bfe7 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
@@ -23,7 +23,6 @@
import androidx.annotation.NonNull;
import androidx.camera.core.CameraUnavailableException;
import androidx.camera.core.InitializationException;
-import androidx.camera.core.UseCase;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.core.impl.utils.futures.Futures;
import androidx.concurrent.futures.CallbackToFutureAdapter;
@@ -40,11 +39,9 @@
/**
* A collection of {@link CameraInternal} instances.
*/
-public final class CameraRepository implements UseCaseMediator.StateChangeCallback {
+public final class CameraRepository {
private static final String TAG = "CameraRepository";
-
private final Object mCamerasLock = new Object();
-
@GuardedBy("mCamerasLock")
private final Map<String, CameraInternal> mCameras = new LinkedHashMap<>();
@GuardedBy("mCamerasLock")
@@ -53,7 +50,6 @@
private ListenableFuture<Void> mDeinitFuture;
@GuardedBy("mCamerasLock")
private CallbackToFutureAdapter.Completer<Void> mDeinitCompleter;
-
/**
* Initializes the repository from a {@link Context}.
*
@@ -72,7 +68,6 @@
}
}
}
-
/**
* Clear and release all cameras from the repository.
*/
@@ -85,7 +80,6 @@
if (mCameras.isEmpty()) {
return mDeinitFuture == null ? Futures.immediateFuture(null) : mDeinitFuture;
}
-
ListenableFuture<Void> currentFuture = mDeinitFuture;
if (currentFuture == null) {
// Create a single future that will be used to track closing of all cameras.
@@ -101,7 +95,6 @@
});
mDeinitFuture = currentFuture;
}
-
// Ensure all of the cameras have been added here before we start releasing so that
// if the first camera release finishes inline it won't complete the future prematurely.
mReleasingCameras.addAll(mCameras.values());
@@ -126,15 +119,12 @@
}
}, CameraXExecutors.directExecutor());
}
-
// Ensure all cameras are removed from the active "mCameras" map. This map can be
// repopulated by #init().
mCameras.clear();
-
return currentFuture;
}
}
-
/**
* Gets a {@link CameraInternal} for the given id.
*
@@ -146,15 +136,12 @@
public CameraInternal getCamera(@NonNull String cameraId) {
synchronized (mCamerasLock) {
CameraInternal cameraInternal = mCameras.get(cameraId);
-
if (cameraInternal == null) {
throw new IllegalArgumentException("Invalid camera: " + cameraId);
}
-
return cameraInternal;
}
}
-
/**
* Gets the set of all cameras.
*
@@ -166,7 +153,6 @@
return new LinkedHashSet<>(mCameras.values());
}
}
-
/**
* Gets the set of all camera ids.
*
@@ -178,53 +164,4 @@
return new LinkedHashSet<>(mCameras.keySet());
}
}
-
- /**
- * Attaches all the use cases in the {@link UseCaseMediator} and opens all the associated
- * cameras.
- *
- * <p>This will start streaming data to the uses cases which are also online.
- */
- @Override
- public void onActive(@NonNull UseCaseMediator useCaseMediator) {
- synchronized (mCamerasLock) {
- Map<String, Set<UseCase>> cameraIdToUseCaseMap =
- useCaseMediator.getCameraIdToUseCaseMap();
- for (Map.Entry<String, Set<UseCase>> cameraUseCaseEntry :
- cameraIdToUseCaseMap.entrySet()) {
- CameraInternal cameraInternal = getCamera(cameraUseCaseEntry.getKey());
- attachUseCasesToCamera(cameraInternal, cameraUseCaseEntry.getValue());
- }
- }
- }
-
- /** Attaches a set of use cases to a camera. */
- @GuardedBy("mCamerasLock")
- private void attachUseCasesToCamera(CameraInternal cameraInternal, Set<UseCase> useCases) {
- cameraInternal.attachUseCases(useCases);
- }
-
- /**
- * Detaches all the use cases in the {@link UseCaseMediator} and closes the camera with no
- * attached
- * use cases.
- */
- @Override
- public void onInactive(@NonNull UseCaseMediator useCaseMediator) {
- synchronized (mCamerasLock) {
- Map<String, Set<UseCase>> cameraIdToUseCaseMap =
- useCaseMediator.getCameraIdToUseCaseMap();
- for (Map.Entry<String, Set<UseCase>> cameraUseCaseEntry :
- cameraIdToUseCaseMap.entrySet()) {
- CameraInternal cameraInternal = getCamera(cameraUseCaseEntry.getKey());
- detachUseCasesFromCamera(cameraInternal, cameraUseCaseEntry.getValue());
- }
- }
- }
-
- /** Detaches a set of use cases from a camera. */
- @GuardedBy("mCamerasLock")
- private void detachUseCasesFromCamera(CameraInternal cameraInternal, Set<UseCase> useCases) {
- cameraInternal.detachUseCases(useCases);
- }
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java
deleted file mode 100644
index 4703e74..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseMediator.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core.impl;
-
-import android.util.Log;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.camera.core.UseCase;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A collection of {@link UseCase}.
- *
- * <p>The set of {@link UseCase} instances have synchronized interactions with the {@link
- * CameraInternal}.
- */
-
-public final class UseCaseMediator {
- private static final String TAG = "UseCaseMediator";
-
- /**
- * The lock for the single {@link StateChangeCallback} held by the mediator.
- *
- * <p>This lock is always acquired prior to acquiring the mUseCasesLock so that there is no
- * lock-ordering deadlock.
- */
- private final Object mListenerLock = new Object();
- /**
- * The lock for accessing the map of use case types to use case instances.
- *
- * <p>This lock is always acquired after acquiring the mListenerLock so that there is no
- * lock-ordering deadlock.
- */
- private final Object mUseCasesLock = new Object();
- @GuardedBy("mUseCasesLock")
- private final Set<UseCase> mUseCases = new HashSet<>();
- @GuardedBy("mListenerLock")
- private StateChangeCallback mStateChangeCallback;
- private volatile boolean mIsActive = false;
-
- /** Starts all the use cases so that they are brought into an online state. */
- public void start() {
- synchronized (mListenerLock) {
- if (mStateChangeCallback != null) {
- mStateChangeCallback.onActive(this);
- }
- mIsActive = true;
- }
- }
-
- /** Stops all the use cases so that they are brought into an offline state. */
- public void stop() {
- synchronized (mListenerLock) {
- if (mStateChangeCallback != null) {
- mStateChangeCallback.onInactive(this);
- }
- mIsActive = false;
- }
- }
-
- /** Sets the StateChangeCallback listener */
- public void setListener(@NonNull StateChangeCallback stateChangeCallback) {
- synchronized (mListenerLock) {
- this.mStateChangeCallback = stateChangeCallback;
- }
- }
-
- /**
- * Adds the {@link UseCase} to the mediator.
- *
- * @return true if the use case is added, or false if the use case already exists in the
- * mediator.
- */
- public boolean addUseCase(@NonNull UseCase useCase) {
- synchronized (mUseCasesLock) {
- return mUseCases.add(useCase);
- }
- }
-
- /** Returns true if the {@link UseCase} is contained in the mediator. */
- public boolean contains(@NonNull UseCase useCase) {
- synchronized (mUseCasesLock) {
- return mUseCases.contains(useCase);
- }
- }
-
- /**
- * Removes the {@link UseCase} from the mediator.
- *
- * @return Returns true if the use case is removed. Otherwise returns false (if the use case did
- * not exist in the mediator).
- */
- public boolean removeUseCase(@NonNull UseCase useCase) {
- synchronized (mUseCasesLock) {
- return mUseCases.remove(useCase);
- }
- }
-
- /**
- * Called when lifecycle ends. Destroys all use cases in this mediator.
- */
- public void destroy() {
- List<UseCase> useCasesToClear = new ArrayList<>();
- synchronized (mUseCasesLock) {
- useCasesToClear.addAll(mUseCases);
- mUseCases.clear();
- }
-
- for (UseCase useCase : useCasesToClear) {
- Log.d(TAG, "Destroying use case: " + useCase.getName());
- useCase.onDetach(useCase.getCamera());
- useCase.onDestroy();
- }
- }
-
- /**
- * Returns the collection of all the use cases currently contained by
- * the{@link UseCaseMediator}.
- */
- @NonNull
- public Collection<UseCase> getUseCases() {
- synchronized (mUseCasesLock) {
- return Collections.unmodifiableCollection(mUseCases);
- }
- }
-
- /** Returns the map of all the use cases to its attached camera id. */
- @NonNull
- public Map<String, Set<UseCase>> getCameraIdToUseCaseMap() {
- Map<String, Set<UseCase>> cameraIdToUseCases = new HashMap<>();
- synchronized (mUseCasesLock) {
- for (UseCase useCase : mUseCases) {
- CameraInternal attachedCamera = useCase.getCamera();
- if (attachedCamera != null) {
- String cameraId = attachedCamera.getCameraInfoInternal().getCameraId();
- Set<UseCase> useCaseSet = cameraIdToUseCases.get(cameraId);
- if (useCaseSet == null) {
- useCaseSet = new HashSet<>();
- }
- useCaseSet.add(useCase);
- cameraIdToUseCases.put(cameraId, useCaseSet);
- }
- }
- }
- return Collections.unmodifiableMap(cameraIdToUseCases);
- }
-
- public boolean isActive() {
- return mIsActive;
- }
-
- /**
- * Listener called when a {@link UseCaseMediator} transitions between active/inactive states
- * .
- */
- public interface StateChangeCallback {
- /**
- * Called when a {@link UseCaseMediator} becomes active.
- *
- * <p>When a {@link UseCaseMediator} is active then all the contained {@link UseCase} become
- * online. This means that the {@link CameraInternal} should transition to a state as
- * close as possible to producing, but prior to actually producing data for the use case.
- */
- void onActive(@NonNull UseCaseMediator useCaseMediator);
-
- /**
- * Called when a {@link UseCaseMediator} becomes inactive.
- *
- * <p>When a {@link UseCaseMediator} is active then all the contained {@link UseCase} become
- * offline.
- */
- void onInactive(@NonNull UseCaseMediator useCaseMediator);
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
index ae1a46b..30ae34b 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -32,26 +32,36 @@
import androidx.camera.core.impl.CameraInternal;
import androidx.camera.core.impl.SurfaceConfig;
import androidx.camera.core.impl.UseCaseConfig;
+import androidx.core.util.Preconditions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
/**
* A {@link CameraInternal} adapter which checks that the UseCases to make sure that the resolutions
* and image formats can be supported.
+ *
+ * <p> The CameraUseCaseAdapter wraps a set of CameraInternals which it can dynamically switch
+ * between based on different configurations that are required by the adapter. This is used by
+ * extensions in order to select the correct CameraInternal instance which has the required
+ * camera id.
*/
public final class CameraUseCaseAdapter {
private final CameraInternal mCameraInternal;
+ private final LinkedHashSet<CameraInternal> mCameraInternals;
private final CameraDeviceSurfaceManager mCameraDeviceSurfaceManager;
private static final String TAG = "CameraUseCaseAdapter";
+ private final CameraId mId;
+
@GuardedBy("mLock")
- private final List<UseCase> mAttachedUseCases = new ArrayList<>();
+ private final List<UseCase> mUseCases = new ArrayList<>();
@GuardedBy("mLock")
@Nullable
@@ -59,20 +69,52 @@
private final Object mLock = new Object();
+ // This indicates whether or not the UseCases that have been added to this adapter has
+ // actually been attached to the CameraInternal instance.
+ @GuardedBy("mLock")
+ private boolean mAttached = true;
+
/**
* Create a new {@link CameraUseCaseAdapter} instance.
*
- * @param cameraInternal the actual camera implementation that is wrapped
+ * @param cameraInternal the actual camera implementation that is current attached
+ * @param cameras the set of cameras that are wrapped
* @param cameraDeviceSurfaceManager A class that checks for whether a specific camera
* can support the set of Surface with set resolutions.
*/
public CameraUseCaseAdapter(@NonNull CameraInternal cameraInternal,
+ @NonNull LinkedHashSet<CameraInternal> cameras,
@NonNull CameraDeviceSurfaceManager cameraDeviceSurfaceManager) {
mCameraInternal = cameraInternal;
+ mCameraInternals = new LinkedHashSet<>(cameras);
+ mId = new CameraId(mCameraInternals);
mCameraDeviceSurfaceManager = cameraDeviceSurfaceManager;
}
/**
+ * Generate a identifier for the set of {@link CameraInternal}.
+ */
+ @NonNull
+ public static CameraId generateCameraId(@NonNull LinkedHashSet<CameraInternal> cameras) {
+ return new CameraId(cameras);
+ }
+
+ /**
+ * Returns the identifier for this {@link CameraUseCaseAdapter}.
+ */
+ @NonNull
+ public CameraId getCameraId() {
+ return mId;
+ }
+
+ /**
+ * Returns true if the {@link CameraUseCaseAdapter} is an equivalent camera.
+ */
+ public boolean isEquivalent(@NonNull CameraUseCaseAdapter cameraUseCaseAdapter) {
+ return mId.equals(cameraUseCaseAdapter.getCameraId());
+ }
+
+ /**
* Set the viewport that will be used for the {@link UseCase} attached to the camera.
*/
public void setViewPort(@Nullable ViewPort viewPort) {
@@ -85,8 +127,6 @@
* Check to see if the set of {@link UseCase} can be attached to the camera.
*
* <p> This does not take into account UseCases which are already attached to the camera.
- *
- * @throws CameraException
*/
public void checkAttachUseCases(@NonNull List<UseCase> useCases) throws CameraException {
// Only do resolution calculation if UseCases were bound
@@ -104,19 +144,19 @@
}
/**
- * Attach the specified collection of {@link UseCase} to the camera.
+ * Add the specified collection of {@link UseCase} to the adapter.
*
- * @throws CameraException Thrown if the combination of newly attached UseCases and the
- * currently attached UseCases exceed the capability of the camera.
+ * @throws CameraException Thrown if the combination of newly added UseCases and the
+ * currently added UseCases exceed the capability of the camera.
*/
@UseExperimental(markerClass = androidx.camera.core.ExperimentalUseCaseGroup.class)
- public void attachUseCases(@NonNull Collection<UseCase> useCases) throws CameraException {
+ public void addUseCases(@NonNull Collection<UseCase> useCases) throws CameraException {
synchronized (mLock) {
- List<UseCase> useCaseListAfterUpdate = new ArrayList<>(mAttachedUseCases);
+ List<UseCase> useCaseListAfterUpdate = new ArrayList<>(mUseCases);
List<UseCase> newUseCases = new ArrayList<>();
for (UseCase useCase : useCases) {
- if (mAttachedUseCases.contains(useCase)) {
+ if (mUseCases.contains(useCase)) {
Log.e(TAG, "Attempting to attach already attached UseCase");
} else {
useCaseListAfterUpdate.add(useCase);
@@ -133,8 +173,8 @@
Map<UseCase, Size> suggestedResolutionsMap;
try {
suggestedResolutionsMap =
- calculateSuggestedResolutions(newUseCases, mAttachedUseCases);
- } catch (IllegalArgumentException e) {
+ calculateSuggestedResolutions(newUseCases, mUseCases);
+ } catch (IllegalArgumentException e) {
throw new CameraException(e.getMessage());
}
@@ -157,23 +197,26 @@
// Do all attaching related work
for (UseCase useCase : newUseCases) {
useCase.onAttach(mCameraInternal);
- useCase.updateSuggestedResolution(suggestedResolutionsMap.get(useCase));
+ useCase.updateSuggestedResolution(
+ Preconditions.checkNotNull(suggestedResolutionsMap.get(useCase)));
}
- mAttachedUseCases.addAll(newUseCases);
- mCameraInternal.attachUseCases(newUseCases);
+ mUseCases.addAll(newUseCases);
+ if (mAttached) {
+ mCameraInternal.attachUseCases(newUseCases);
+ }
}
}
/**
- * Detached the specified collection of {@link UseCase} from the camera.
+ * Remove the specified collection of {@link UseCase} from the adapter.
*/
- public void detachUseCases(@NonNull Collection<UseCase> useCases) {
+ public void removeUseCases(@NonNull Collection<UseCase> useCases) {
synchronized (mLock) {
mCameraInternal.detachUseCases(useCases);
for (UseCase useCase : useCases) {
- if (mAttachedUseCases.contains(useCase)) {
+ if (mUseCases.contains(useCase)) {
useCase.onDetach(mCameraInternal);
useCase.onDestroy();
} else {
@@ -181,7 +224,49 @@
}
}
- mAttachedUseCases.removeAll(useCases);
+ mUseCases.removeAll(useCases);
+ }
+ }
+
+ /**
+ * Returns the UseCases currently associated with the adapter.
+ *
+ * <p> The UseCases may or may not be actually attached to the underlying
+ * {@link CameraInternal} instance.
+ */
+ @NonNull
+ public List<UseCase> getUseCases() {
+ synchronized (mLock) {
+ return mUseCases;
+ }
+ }
+
+ /**
+ * Attach the UseCases to the {@link CameraInternal} camera so that the UseCases can receive
+ * data if they are active.
+ *
+ * <p> This will start the underlying {@link CameraInternal} instance.
+ */
+ public void attachUseCases() {
+ synchronized (mLock) {
+ if (!mAttached) {
+ mCameraInternal.attachUseCases(mUseCases);
+ mAttached = true;
+ }
+ }
+ }
+
+ /**
+ * Detach the UseCases from the {@link CameraInternal} so that the UseCases stop receiving data.
+ *
+ * <p> This will stop the underlying {@link CameraInternal} instance.
+ */
+ public void detachUseCases() {
+ synchronized (mLock) {
+ if (mAttached) {
+ mCameraInternal.detachUseCases(mUseCases);
+ mAttached = false;
+ }
}
}
@@ -224,14 +309,6 @@
return suggestedResolutions;
}
- /**
- * Get the {@link CameraInternal} instance that is wrapped by this {@link CameraUseCaseAdapter}.
- */
- @NonNull
- public CameraInternal getCameraInternal() {
- return mCameraInternal;
- }
-
@NonNull
public CameraInfoInternal getCameraInfoInternal() {
return mCameraInternal.getCameraInfoInternal();
@@ -243,6 +320,36 @@
}
/**
+ * An identifier for a {@link CameraUseCaseAdapter}.
+ *
+ * <p>This identifies the actual camera instances that are wrapped by the
+ * CameraUseCaseAdapter and is used to determine if 2 different instances of
+ * CameraUseCaseAdapter are actually equivalent.
+ */
+ public static final class CameraId {
+ private final List<String> mIds;
+ CameraId(LinkedHashSet<CameraInternal> cameraInternals) {
+ mIds = new ArrayList<>();
+ for (CameraInternal cameraInternal : cameraInternals) {
+ mIds.add(cameraInternal.getCameraInfoInternal().getCameraId());
+ }
+ }
+
+ @Override
+ public boolean equals(Object cameraId) {
+ if (cameraId instanceof CameraId) {
+ return mIds.equals(((CameraId) cameraId).mIds);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 53 * mIds.hashCode();
+ }
+ }
+
+ /**
* An exception thrown when the {@link CameraUseCaseAdapter} errors in one of its operations.
*/
public static final class CameraException extends Exception {
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java b/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
index b10f261..60de785 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/CameraSelectorTest.java
@@ -19,24 +19,16 @@
import static org.mockito.Mockito.mock;
-import android.content.Context;
import android.os.Build;
import androidx.annotation.experimental.UseExperimental;
import androidx.camera.core.impl.CameraControlInternal;
-import androidx.camera.core.impl.CameraDeviceSurfaceManager;
import androidx.camera.core.impl.CameraInternal;
-import androidx.camera.core.impl.ExtendableUseCaseConfigFactory;
-import androidx.camera.core.impl.UseCaseConfigFactory;
import androidx.camera.testing.fakes.FakeCamera;
-import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager;
import androidx.camera.testing.fakes.FakeCameraFactory;
import androidx.camera.testing.fakes.FakeCameraInfoInternal;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
-import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,16 +54,6 @@
@Before
public void setUp() throws ExecutionException, InterruptedException {
- Context context = ApplicationProvider.getApplicationContext();
- CameraDeviceSurfaceManager.Provider surfaceManagerProvider =
- ignored -> new FakeCameraDeviceSurfaceManager();
- UseCaseConfigFactory.Provider configFactoryProvider = ignored -> {
- ExtendableUseCaseConfigFactory defaultConfigFactory =
- new ExtendableUseCaseConfigFactory();
- defaultConfigFactory.installDefaultProvider(FakeUseCaseConfig.class,
- cameraInfo -> new FakeUseCaseConfig.Builder().getUseCaseConfig());
- return defaultConfigFactory;
- };
FakeCameraFactory cameraFactory = new FakeCameraFactory();
mRearCamera = new FakeCamera(mock(CameraControlInternal.class),
new FakeCameraInfoInternal(REAR_ROTATION_DEGREE,
@@ -83,17 +65,6 @@
CameraSelector.LENS_FACING_FRONT));
cameraFactory.insertCamera(CameraSelector.LENS_FACING_FRONT, FRONT_ID, () -> mFrontCamera);
mCameras.add(mFrontCamera);
- CameraXConfig.Builder appConfigBuilder =
- new CameraXConfig.Builder()
- .setCameraFactoryProvider((ignored1, ignored2) -> cameraFactory)
- .setDeviceSurfaceManagerProvider(surfaceManagerProvider)
- .setUseCaseConfigFactoryProvider(configFactoryProvider);
- CameraX.initialize(context, appConfigBuilder.build()).get();
- }
-
- @After
- public void tearDown() throws ExecutionException, InterruptedException {
- CameraX.shutdown().get();
}
@Test
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java b/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
index 8f218f4..701319c 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
@@ -111,7 +111,8 @@
public void camerasAreReleasedByDeinit() throws ExecutionException, InterruptedException {
List<CameraInternal> cameraInternals = new ArrayList<>();
for (String cameraId : mCameraRepository.getCameraIds()) {
- cameraInternals.add(mCameraRepository.getCamera(cameraId));
+ cameraInternals.add(
+ mCameraRepository.getCamera(cameraId));
}
ListenableFuture<Void> deinitFuture = mCameraRepository.deinit();
diff --git a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
index d7c6615..01f99dc 100644
--- a/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
+++ b/camera/camera-lifecycle/src/androidTest/java/androidx/camera/lifecycle/ProcessCameraProviderTest.kt
@@ -19,6 +19,7 @@
import androidx.camera.core.CameraSelector
import androidx.annotation.experimental.UseExperimental
import androidx.camera.core.CameraXConfig
+import androidx.camera.core.Preview
import androidx.camera.testing.fakes.FakeAppConfig
import androidx.camera.testing.fakes.FakeLifecycleOwner
import androidx.concurrent.futures.await
@@ -37,7 +38,10 @@
class ProcessCameraProviderTest {
private val context = ApplicationProvider.getApplicationContext() as android.content.Context
- private val lifecycleOwner = FakeLifecycleOwner()
+ private val lifecycleOwner0 = FakeLifecycleOwner()
+ private val lifecycleOwner1 = FakeLifecycleOwner()
+
+ private var provider: ProcessCameraProvider? = null
@After
fun tearDown() {
@@ -75,7 +79,7 @@
fun configuredGetInstance_returnsProvider() {
ProcessCameraProvider.configureInstance(FakeAppConfig.create())
runBlocking {
- val provider = ProcessCameraProvider.getInstance(context).await()
+ provider = ProcessCameraProvider.getInstance(context).await()
assertThat(provider).isNotNull()
}
}
@@ -103,10 +107,120 @@
fun canRetrieveCamera_withZeroUseCases() {
ProcessCameraProvider.configureInstance(FakeAppConfig.create())
runBlocking(MainScope().coroutineContext) {
- val provider = ProcessCameraProvider.getInstance(context).await()
+ provider = ProcessCameraProvider.getInstance(context).await()
val camera =
- provider.bindToLifecycle(lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA)
+ provider!!.bindToLifecycle(lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA)
assertThat(camera).isNotNull()
}
}
+
+ @Test
+ fun bindUseCase_isBound() {
+ ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+ runBlocking(MainScope().coroutineContext) {
+ provider = ProcessCameraProvider.getInstance(context).await()
+ val useCase = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+ provider!!.bindToLifecycle(
+ lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA,
+ useCase
+ )
+
+ assertThat(provider!!.isBound(useCase)).isTrue()
+ }
+ }
+
+ @Test
+ fun bindSecondUseCaseToDifferentLifecycle_firstUseCaseStillBound() {
+ ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+ runBlocking(MainScope().coroutineContext) {
+ provider = ProcessCameraProvider.getInstance(context).await()
+
+ val useCase0 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+ val useCase1 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+ provider!!.bindToLifecycle(
+ lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA,
+ useCase0
+ )
+ provider!!.bindToLifecycle(
+ lifecycleOwner1, CameraSelector.DEFAULT_BACK_CAMERA,
+ useCase1
+ )
+
+ // TODO(b/158595693) Add check on whether or not camera for fakeUseCase0 should be
+ // exist or not
+ // assertThat(fakeUseCase0.camera).isNotNull() (or isNull()?)
+ assertThat(provider!!.isBound(useCase0)).isTrue()
+ assertThat(useCase1.camera).isNotNull()
+ assertThat(provider!!.isBound(useCase1)).isTrue()
+ }
+ }
+
+ @Test
+ fun isNotBound_afterUnbind() {
+ ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+ runBlocking(MainScope().coroutineContext) {
+ provider = ProcessCameraProvider.getInstance(context).await()
+
+ val useCase = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+ provider!!.bindToLifecycle(
+ lifecycleOwner0,
+ CameraSelector.DEFAULT_BACK_CAMERA,
+ useCase
+ )
+
+ provider!!.unbind(useCase)
+
+ assertThat(provider!!.isBound(useCase)).isFalse()
+ }
+ }
+
+ @Test
+ fun unbindFirstUseCase_secondUseCaseStillBound() {
+ ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+ runBlocking(MainScope().coroutineContext) {
+ provider = ProcessCameraProvider.getInstance(context).await()
+
+ val useCase0 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+ val useCase1 = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+ provider!!.bindToLifecycle(
+ lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA,
+ useCase0, useCase1
+ )
+
+ provider!!.unbind(useCase0)
+
+ assertThat(useCase0.camera).isNull()
+ assertThat(provider!!.isBound(useCase0)).isFalse()
+ assertThat(useCase1.camera).isNotNull()
+ assertThat(provider!!.isBound(useCase1)).isTrue()
+ }
+ }
+
+ @Test
+ fun unbindAll_unbindsAllUseCasesFromCameras() {
+ ProcessCameraProvider.configureInstance(FakeAppConfig.create())
+
+ runBlocking(MainScope().coroutineContext) {
+ provider = ProcessCameraProvider.getInstance(context).await()
+
+ val useCase = Preview.Builder().setSessionOptionUnpacker { _, _ -> }.build()
+
+ provider!!.bindToLifecycle(
+ lifecycleOwner0, CameraSelector.DEFAULT_BACK_CAMERA, useCase
+ )
+
+ provider!!.unbindAll()
+
+ assertThat(useCase.camera).isNull()
+ assertThat(provider!!.isBound(useCase)).isFalse()
+ }
+ }
}
\ No newline at end of file
diff --git a/camera/camera-testing/build.gradle b/camera/camera-testing/build.gradle
index ee9ec74..acdf19e 100644
--- a/camera/camera-testing/build.gradle
+++ b/camera/camera-testing/build.gradle
@@ -26,6 +26,7 @@
dependencies {
implementation("androidx.test:core:1.2.0")
+ implementation(ANDROIDX_TEST_RULES)
implementation(ANDROIDX_TEST_UIAUTOMATOR)
api("androidx.annotation:annotation:1.0.0")
implementation(GUAVA_LISTENABLE_FUTURE)
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
index 8acc0b4..9544a65 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/CameraUtil.java
@@ -16,7 +16,10 @@
package androidx.camera.testing;
+import static org.junit.Assume.assumeTrue;
+
import android.Manifest;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
@@ -39,9 +42,15 @@
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.core.util.Preconditions;
import androidx.test.core.app.ApplicationProvider;
+import androidx.test.rule.GrantPermissionRule;
import com.google.common.util.concurrent.ListenableFuture;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -58,6 +67,9 @@
/** Amount of time to wait before timing out when trying to open a {@link CameraDevice}. */
private static final int CAMERA_OPEN_TIMEOUT_SECONDS = 2;
+ /** The device debug property key for the tests to enable the camera pretest. */
+ private static final String PRETEST_CAMERA_TAG = "PreTestCamera";
+
/**
* Gets a new instance of a {@link CameraDevice}.
*
@@ -444,4 +456,117 @@
"Unable to retrieve info for camera with id " + cameraId + ".", e);
}
}
+
+ /**
+ * Create a chained rule for the test cases that need to use the camera.
+ *
+ * <p>It will
+ * (1) Grant the camera permission.
+ * (2) Check if there is at least one camera on the device.
+ * (3) Test the camera can be opened successfully.
+ *
+ * <p>The method will set PreTestCamera throw exception will set when the PRETEST_CAMERA_TAG
+ * debug key for Log.isLoggable is enabled.
+ */
+ @NonNull
+ public static RuleChain grantCameraPermissionAndPreTest() {
+ return RuleChain.outerRule(GrantPermissionRule.grant(Manifest.permission.CAMERA)).around(
+ (base, description) -> new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ assumeTrue(deviceHasCamera());
+ base.evaluate();
+ }
+ }).around(
+ new CameraUtil.PreTestCamera(Log.isLoggable(PRETEST_CAMERA_TAG, Log.DEBUG)));
+ }
+
+ /**
+ * Pretest the camera device
+ *
+ * <p>Try to open the camera with the front and back lensFacing. It throws exception when
+ * camera is unavailable and mThrowOnError is true.
+ *
+ * <p>Passing false into the constructor {@link #PreTestCamera(boolean)}
+ * will never throw the exception when the camera is unavailable.
+ */
+ public static class PreTestCamera implements TestRule {
+ final boolean mThrowOnError;
+
+ public PreTestCamera(boolean throwOnError) {
+ mThrowOnError = throwOnError;
+ }
+
+ @NonNull
+ @Override
+ public Statement apply(@NonNull Statement base, @NonNull Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ boolean backStatus = true;
+ if (hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK)) {
+ Log.w(CameraUtil.class.getSimpleName(), "Fail to open the back camera");
+ backStatus = tryOpenCamera(CameraSelector.LENS_FACING_BACK);
+ }
+
+ boolean frontStatus = true;
+ if (hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT)) {
+ Log.w(CameraUtil.class.getSimpleName(), "Fail to open the front camera");
+ frontStatus = tryOpenCamera(CameraSelector.LENS_FACING_FRONT);
+ }
+ boolean canOpenCamera = backStatus && frontStatus;
+
+ if (canOpenCamera) {
+ base.evaluate();
+ } else {
+ if (mThrowOnError) {
+ throw new RuntimeException(
+ "CameraX_cannot_test_with_failed_camera, model:" + Build.MODEL);
+ } else {
+ // Ignore the test, so we only print a log without calling
+ Log.w(CameraUtil.class.getSimpleName(),
+ "Camera fail, on test " + description.getDisplayName());
+ base.evaluate();
+ }
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * Try to open the camera, and close it immediately.
+ *
+ * @param lensFacing the lensFacing of the camera to test
+ * @return true if the camera can be opened successfully
+ */
+ @SuppressLint("MissingPermission")
+ public static boolean tryOpenCamera(@CameraSelector.LensFacing int lensFacing) {
+ String cameraId = getCameraIdWithLensFacing(lensFacing);
+
+ if (cameraId == null) {
+ return false;
+ }
+
+ CameraDeviceHolder deviceHolder = null;
+ boolean ret = true;
+ try {
+ deviceHolder = new CameraDeviceHolder(getCameraManager(), cameraId);
+ if (deviceHolder.get() == null) {
+ ret = false;
+ }
+ } catch (Exception e) {
+ ret = false;
+ } finally {
+ if (deviceHolder != null) {
+ try {
+ releaseCameraDevice(deviceHolder);
+ } catch (Exception e) {
+ Log.e(CameraUtil.class.getSimpleName(), "Cannot close cameraDevice.", e);
+ }
+ }
+ }
+
+ return ret;
+ }
}
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
index 0640d95..a03ce63 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCamera.java
@@ -44,7 +44,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* A fake camera which will not produce any data, but provides a valid Camera implementation.
@@ -58,6 +60,7 @@
private final CameraInfoInternal mCameraInfoInternal;
private String mCameraId;
private UseCaseAttachState mUseCaseAttachState;
+ private Set<UseCase> mAttachedUseCases = new HashSet<>();
private State mState = State.CLOSED;
private int mAvailableCameraCount = 1;
@@ -236,6 +239,8 @@
return;
}
+ mAttachedUseCases.addAll(useCases);
+
Log.d(TAG, "Use cases " + useCases + " ATTACHED for camera " + mCameraId);
for (UseCase useCase : useCases) {
mUseCaseAttachState.setUseCaseAttached(useCase.getName() + useCase.hashCode(),
@@ -257,6 +262,8 @@
return;
}
+ mAttachedUseCases.removeAll(useCases);
+
Log.d(TAG, "Use cases " + useCases + " DETACHED for camera " + mCameraId);
for (UseCase useCase : useCases) {
mUseCaseAttachState.setUseCaseDetached(useCase.getName() + useCase.hashCode());
@@ -271,6 +278,11 @@
updateCaptureSessionConfig();
}
+ @NonNull
+ public Set<UseCase> getAttachedUseCases() {
+ return mAttachedUseCases;
+ }
+
// Returns fixed CameraControlInternal instance in order to verify the instance is correctly
// attached.
@NonNull
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java
index 665a5ee..b013a1f 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewViewImplementation.java
@@ -138,19 +138,18 @@
final Bitmap scaled = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), scale, true);
- // If fit* scale type, return scaled bitmap, since the whole preview is displayed, no
- // cropping is needed.
final PreviewView.ScaleType scaleType = mPreviewTransform.getScaleType();
- if (scaleType == PreviewView.ScaleType.FIT_START
- || scaleType == PreviewView.ScaleType.FIT_CENTER
- || scaleType == PreviewView.ScaleType.FIT_END) {
- return scaled;
- }
- // If fill* scale type, crop the scaled bitmap, then return it
Preconditions.checkNotNull(mParent);
int x = 0, y = 0;
switch (scaleType) {
+ // If fit* scale type, return scaled bitmap, since the whole preview is displayed, no
+ // cropping is needed.
+ case FIT_START:
+ case FIT_CENTER:
+ case FIT_END:
+ return scaled;
+ // If fill* scale type, crop the scaled bitmap, then return it
case FILL_START:
x = 0;
y = 0;
diff --git a/camera/integration-tests/coretestapp/build.gradle b/camera/integration-tests/coretestapp/build.gradle
index 7f6c5cd..af069b9 100644
--- a/camera/integration-tests/coretestapp/build.gradle
+++ b/camera/integration-tests/coretestapp/build.gradle
@@ -40,14 +40,6 @@
}
}
- sourceSets {
- main.manifest.srcFile 'src/main/AndroidManifest.xml'
- main.java.srcDirs = ['src/main/java']
- main.java.excludes = ['**/build/**']
- main.java.includes = ['**/*.java']
- main.res.srcDirs = ['src/main/res']
- }
-
buildTypes {
debug {
pseudoLocalesEnabled true
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXActivityTestExtensions.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXActivityTestExtensions.kt
new file mode 100644
index 0000000..3a465b5
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraXActivityTestExtensions.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.core
+
+import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.IdlingRegistry
+import androidx.test.espresso.assertion.ViewAssertions
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.testutils.withActivity
+
+/**
+ * Waits until the viewfinder has received frames and its idling resource has become idle.
+ */
+internal fun ActivityScenario<CameraXActivity>.waitForViewfinderIdle() {
+ val idlingResource = withActivity { viewIdlingResource }
+ try {
+ IdlingRegistry.getInstance().register(idlingResource)
+ // Check the activity launched and Preview displays frames.
+ Espresso.onView(ViewMatchers.withId(R.id.viewFinder))
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ } finally { // Always release the idling resource, in case of timeout exceptions.
+ IdlingRegistry.getInstance().unregister(idlingResource)
+ }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.java b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.java
deleted file mode 100644
index 0d69f3f..0000000
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.integration.core;
-
-import static androidx.camera.testing.CoreAppTestUtil.clearDeviceUI;
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.pm.ActivityInfo;
-
-import androidx.camera.core.CameraSelector;
-import androidx.camera.testing.CameraUtil;
-import androidx.camera.testing.CoreAppTestUtil;
-import androidx.lifecycle.Lifecycle;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.espresso.IdlingRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.GrantPermissionRule;
-import androidx.test.uiautomator.UiDevice;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-// Test application lifecycle when using CameraX.
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public final class ExistingActivityLifecycleTest {
- private static final int HOME_TIMEOUT_MS = 3000;
-
- private final UiDevice mDevice =
- UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- private final String mLauncherPackageName = mDevice.getLauncherPackageName();
-
- @Rule
- public GrantPermissionRule mCameraPermissionRule =
- GrantPermissionRule.grant(android.Manifest.permission.CAMERA);
- @Rule
- public GrantPermissionRule mStoragePermissionRule =
- GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
- @Rule
- public GrantPermissionRule mAudioPermissionRule =
- GrantPermissionRule.grant(android.Manifest.permission.RECORD_AUDIO);
-
- @Before
- public void setup() {
- assumeTrue(CameraUtil.deviceHasCamera());
- CoreAppTestUtil.assumeCompatibleDevice();
- assertThat(mLauncherPackageName, notNullValue());
-
- // Clear the device UI before start each test.
- clearDeviceUI(InstrumentationRegistry.getInstrumentation());
- }
-
- @After
- public void tearDown() {
- mDevice.pressHome();
- mDevice.waitForIdle(HOME_TIMEOUT_MS);
- }
-
- // Check if Preview screen is updated or not, after Destroy-Create lifecycle.
- @Test
- public void checkPreviewUpdatedAfterDestroyRecreate() {
- // Launch activity.
- try (ActivityScenario<CameraXActivity> activityScenario =
- ActivityScenario.launch(CameraXActivity.class)) {
- // Check for view idle, then destroy it.
- checkForViewIdle(activityScenario);
- // Launch new activity and check for view idle.
- checkForViewIdle(activityScenario.recreate());
- }
- }
-
- // Check if Preview screen is updated or not, after Stop-Resume lifecycle.
- @Test
- public void checkPreviewUpdatedAfterStopResume() {
- // Launch activity.
- try (ActivityScenario<CameraXActivity> activityScenario =
- ActivityScenario.launch(CameraXActivity.class)) {
- // Check view gets to idle.
- checkForViewIdle(activityScenario);
- // Go through pause/resume then check again for view to get frames then idle.
- activityScenario.moveToState(Lifecycle.State.CREATED).onActivity(activity -> {
- activity.resetViewIdlingResource();
- });
- checkForViewIdle(activityScenario.moveToState(Lifecycle.State.RESUMED));
-
- // Go through pause/resume then check again for view to get frames then idle, the
- // second pass is used to protect against previous observed issues.
- activityScenario.moveToState(Lifecycle.State.CREATED).onActivity(activity -> {
- activity.resetViewIdlingResource();
- });
- checkForViewIdle(activityScenario.moveToState(Lifecycle.State.RESUMED));
- }
- }
-
- // Check if Preview screen is updated or not, after toggling camera, then a Destroy-Create
- // lifecycle.
- @Test
- public void checkPreviewUpdatedAfterToggleCameraAndStopResume() {
- // check have front camera
- assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT));
- try (ActivityScenario<CameraXActivity> activityScenario =
- ActivityScenario.launch(CameraXActivity.class)) {
- try {
- activityScenario.onActivity(activity -> {
- IdlingRegistry.getInstance().register(activity.getViewIdlingResource());
- });
- onView(withId(R.id.viewFinder)).check(matches(isDisplayed()));
- // Switch camera.
- onView(withId(R.id.direction_toggle)).perform(click());
- // Go through pause/resume then check again for view to get frames then idle.
- activityScenario.moveToState(Lifecycle.State.CREATED);
- activityScenario.onActivity(activity -> {
- activity.resetViewIdlingResource();
- });
- activityScenario.moveToState(Lifecycle.State.RESUMED);
- onView(withId(R.id.viewFinder)).check(matches(isDisplayed()));
- } finally {
- activityScenario.onActivity(activity -> {
- IdlingRegistry.getInstance().unregister(activity.getViewIdlingResource());
- });
- }
- }
- }
-
- // Check if Preview screen is updated or not, after rotate device, and Stop-Resume lifecycle.
- @Test
- public void checkPreviewUpdatedAfterRotateDeviceAndStopResume() {
- // Launch activity.
- try (ActivityScenario<CameraXActivity> activityScenario =
- checkForViewIdle(ActivityScenario.launch(CameraXActivity.class))) {
- // Check view gets to idle.
- checkForViewIdle(activityScenario);
- // Rotate to Landscape and the activity will be recreated.
- activityScenario.onActivity(activity -> {
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- });
- // Get idling from the re-created activity.
- activityScenario.onActivity(activity -> {
- activity.resetViewIdlingResource();
- });
- checkForViewIdle(activityScenario);
-
- activityScenario.moveToState(Lifecycle.State.CREATED);
- activityScenario.onActivity(activity -> {
- activity.resetViewIdlingResource();
- });
- activityScenario.moveToState(Lifecycle.State.RESUMED);
-
- checkForViewIdle(activityScenario);
- }
- }
-
- private ActivityScenario<CameraXActivity>
- checkForViewIdle(ActivityScenario<CameraXActivity> activityScenario) {
- try {
- activityScenario.onActivity(activity -> {
- IdlingRegistry.getInstance().register(activity.getViewIdlingResource());
- });
- // Check the activity launched and Preview displays frames.
- onView(withId(R.id.viewFinder)).check(matches(isDisplayed()));
- } finally {
- // Always release the idling resource, in case of timeout exceptions.
- activityScenario.onActivity(activity -> {
- IdlingRegistry.getInstance().unregister(activity.getViewIdlingResource());
- });
- }
- return activityScenario;
- }
-}
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.kt
new file mode 100644
index 0000000..857a8ee
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ExistingActivityLifecycleTest.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.camera.integration.core
+
+import android.Manifest
+import android.app.Instrumentation
+import androidx.camera.core.CameraSelector
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CoreAppTestUtil
+import androidx.lifecycle.Lifecycle.State.CREATED
+import androidx.lifecycle.Lifecycle.State.RESUMED
+import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.GrantPermissionRule
+import androidx.test.uiautomator.UiDevice
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val HOME_TIMEOUT_MS = 3000L
+private const val ROTATE_TIMEOUT_MS = 2000L
+
+// Test application lifecycle when using CameraX.
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class ExistingActivityLifecycleTest {
+ private val mDevice =
+ UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ private val mLauncherPackageName = mDevice.launcherPackageName
+
+ @get:Rule
+ val mPermissionRule: GrantPermissionRule =
+ GrantPermissionRule.grant(
+ Manifest.permission.CAMERA,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.RECORD_AUDIO
+ )
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(CameraUtil.deviceHasCamera())
+ CoreAppTestUtil.assumeCompatibleDevice()
+ assertThat(mLauncherPackageName).isNotNull()
+ // Clear the device UI before start each test.
+ CoreAppTestUtil.clearDeviceUI(InstrumentationRegistry.getInstrumentation())
+ // Use the natural orientation throughout these tests to ensure the activity isn't
+ // recreated unexpectedly. This will also freeze the sensors until
+ // mDevice.unfreezeRotation() in the tearDown() method. Any simulated rotations will be
+ // explicitly initiated from within the test.
+ mDevice.setOrientationNatural()
+ }
+
+ @After
+ fun tearDown() {
+ // Unfreeze rotation so the device can choose the orientation via its own policy. Be nice
+ // to other tests :)
+ mDevice.unfreezeRotation()
+ mDevice.pressHome()
+ mDevice.waitForIdle(HOME_TIMEOUT_MS)
+ }
+
+ // Check if Preview screen is updated or not, after Destroy-Create lifecycle.
+ @Test
+ fun checkPreviewUpdatedAfterDestroyRecreate() {
+ with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+ use { // Ensure ActivityScenario is cleaned up properly
+ // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+ waitForViewfinderIdle()
+ // Destroy previous activity, launch new activity and check for view idle.
+ recreate()
+ waitForViewfinderIdle()
+ }
+ }
+ }
+
+ // Check if Preview screen is updated or not, after Stop-Resume lifecycle.
+ @Test
+ fun checkPreviewUpdatedAfterStopResume() {
+ with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+ use { // Ensure ActivityScenario is cleaned up properly
+ // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+ waitForViewfinderIdle()
+ // Go through pause/resume then check again for view to get frames then idle.
+ moveToState(CREATED)
+
+ withActivity { resetViewIdlingResource() }
+
+ moveToState(RESUMED)
+
+ waitForViewfinderIdle()
+ // Go through pause/resume then check again for view to get frames then idle,
+ // the second pass is used to protect against previous observed issues.
+ moveToState(CREATED)
+
+ withActivity { resetViewIdlingResource() }
+
+ moveToState(RESUMED)
+
+ waitForViewfinderIdle()
+ }
+ }
+ }
+
+ // Check if Preview screen is updated or not, after toggling camera,
+ // then a Destroy-Create lifecycle.
+ @Test
+ fun checkPreviewUpdatedAfterToggleCameraAndStopResume() = runBlocking {
+ // check have front camera
+ Assume.assumeTrue(
+ CameraUtil.hasCameraWithLensFacing(
+ CameraSelector.LENS_FACING_FRONT
+ )
+ )
+
+ with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+ use { // Ensure ActivityScenario is cleaned up properly
+ // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+ waitForViewfinderIdle()
+
+ // Switch camera.
+ Espresso.onView(ViewMatchers.withId(R.id.direction_toggle))
+ .perform(ViewActions.click())
+
+ // TODO(b/159257773): Currently have no reliable way of checking that camera has
+ // switched. Delay to ensure previous camera has stopped streaming and the
+ // idling resource actually is becoming idle due to frames from front camera.
+ delay(500)
+
+ // Check front camera is now idle
+ withActivity { resetViewIdlingResource() }
+ waitForViewfinderIdle()
+
+ // Go through pause/resume then check again for view to get frames then idle.
+ moveToState(CREATED)
+ withActivity { resetViewIdlingResource() }
+ moveToState(RESUMED)
+ waitForViewfinderIdle()
+ }
+ }
+ }
+
+ // Check if Preview screen is updated or not, after rotate device, and Stop-Resume lifecycle.
+ @Test
+ fun checkPreviewUpdatedAfterRotateDeviceAndStopResume() {
+ with(ActivityScenario.launch(CameraXActivity::class.java)) { // Launch activity.
+ use { // Ensure ActivityScenario is cleaned up properly
+ // Wait for viewfinder to receive enough frames for its IdlingResource to idle.
+ waitForViewfinderIdle()
+
+ // Rotate to the orientation left of natural and wait for the activity to be
+ // recreated.
+ rotateDeviceLeftAndWait()
+
+ // Get idling from the re-created activity.
+ withActivity { resetViewIdlingResource() }
+ waitForViewfinderIdle()
+
+ moveToState(CREATED)
+ withActivity { resetViewIdlingResource() }
+ moveToState(RESUMED)
+ waitForViewfinderIdle()
+ }
+ }
+ }
+
+ private fun rotateDeviceLeftAndWait() {
+ // Create an ActivityMonitor to explicitly wait for the activity to be recreated after
+ // rotating the device.
+ val monitor =
+ Instrumentation.ActivityMonitor(CameraXActivity::class.java.name, null, false)
+ InstrumentationRegistry.getInstrumentation().addMonitor(monitor)
+ mDevice.setOrientationLeft()
+ // Wait for the rotation to complete
+ InstrumentationRegistry.getInstrumentation().waitForMonitorWithTimeout(
+ monitor,
+ ROTATE_TIMEOUT_MS
+ )
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt
index e026c9a..c5660a5 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/LockedOrientationActivityTest.kt
@@ -16,7 +16,6 @@
package androidx.camera.integration.uiwidgets.rotations.imageanalysis
-import android.Manifest
import android.content.Context
import android.content.Intent
import androidx.camera.camera2.Camera2Config
@@ -79,7 +78,7 @@
@get:Rule
val mCameraPermissionRule: GrantPermissionRule =
- GrantPermissionRule.grant(Manifest.permission.CAMERA)
+ GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
@Before
fun setUp() {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt
index 4549155..debff6e 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/OrientationConfigChangesOverriddenActivityTest.kt
@@ -16,7 +16,6 @@
package androidx.camera.integration.uiwidgets.rotations.imageanalysis
-import android.Manifest
import android.content.Context
import android.content.Intent
import android.view.Surface
@@ -82,7 +81,7 @@
@get:Rule
val mCameraPermissionRule: GrantPermissionRule =
- GrantPermissionRule.grant(Manifest.permission.CAMERA)
+ GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
@Before
fun setUp() {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt
index eccd02e..0bc425e 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imageanalysis/UnlockedOrientationActivityTest.kt
@@ -16,7 +16,6 @@
package androidx.camera.integration.uiwidgets.rotations.imageanalysis
-import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
@@ -91,7 +90,7 @@
@get:Rule
val mCameraPermissionRule: GrantPermissionRule =
- GrantPermissionRule.grant(Manifest.permission.CAMERA)
+ GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
@Before
fun setUp() {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/ImageCaptureTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/ImageCaptureTest.kt
new file mode 100644
index 0000000..7bdca52
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/ImageCaptureTest.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.uiwidgets.rotations.imagecapture
+
+import android.content.Intent
+import android.os.Build
+import android.view.View
+import androidx.camera.core.CameraSelector
+import androidx.camera.integration.uiwidgets.R
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CoreAppTestUtil
+import androidx.test.core.app.ActivityScenario
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import java.util.concurrent.TimeUnit
+
+/**
+ * Base class for rotation image capture tests.
+ *
+ * The flow of the tests is:
+ * - Launch the activity
+ * - Wait fo the camera to be set up
+ * - Rotate
+ * - Wait a couple of frames
+ * - Take a picture
+ * - Wait for the image capture callback
+ * - Verify the picture's rotation or resolution
+ */
+abstract class ImageCaptureTest<A : CameraActivity> {
+
+ protected fun setUp(lensFacing: Int) {
+ // TODO(b/147448711) Cuttlefish seems to have an issue handling rotation. Might be
+ // related to the attached bug.
+ assumeFalse(
+ "Cuttlefish does not correctly handle rotating. Unable to test.",
+ Build.MODEL.contains("Cuttlefish")
+ )
+
+ CoreAppTestUtil.assumeCompatibleDevice()
+ Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(lensFacing))
+
+ // Clear the device's UI and ensure it's in a natural orientation
+ CoreAppTestUtil.clearDeviceUI(InstrumentationRegistry.getInstrumentation())
+ val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ device.setOrientationNatural()
+ }
+
+ protected fun tearDown() {
+ val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ device.unfreezeRotation()
+ }
+
+ protected inline fun <reified A : CameraActivity> verifyRotation(
+ lensFacing: Int,
+ captureMode: Int,
+ rotate: ActivityScenario<A>.() -> Unit
+ ) {
+ val activityScenario: ActivityScenario<A> = launchActivity(lensFacing, captureMode)
+ activityScenario.use { scenario ->
+
+ // Wait until the camera is set up and analysis starts receiving frames
+ scenario.waitOnCameraFrames()
+
+ // Rotate
+ rotate(scenario)
+
+ // Wait a couple of frames after rotation
+ scenario.waitOnCameraFrames()
+
+ // Take picture
+ scenario.onActivity {
+ val view = it.findViewById<View>(R.id.previewView)
+ view.performClick()
+ }
+
+ // Wait until a picture is taken and the capture callback is invoked
+ val captureDone = scenario.withActivity { mCaptureDone }
+ assertThat(captureDone.tryAcquire(TIMEOUT, TimeUnit.SECONDS)).isTrue()
+
+ // If the camera HAL doesn't rotate the image, the captured image should contain a
+ // rotation that's equal to the sensor rotation relative to target rotation
+ val (sensorToTargetRotation, imageRotationDegrees) = scenario.withActivity {
+ Pair(
+ getSensorRotationRelativeToCaptureTargetRotation(),
+ mCaptureResult?.getRotation()
+ )
+ }
+ val areRotationsEqual = sensorToTargetRotation == imageRotationDegrees
+
+ // If the camera HAL did rotate the image, verifying the image's rotation isn't
+ // possible, so we make sure the image has the correct orientation/resolution.
+ val (expectedResolution, imageSize) = scenario.withActivity {
+ Pair(getCaptureResolution(), mCaptureResult?.getResolution())
+ }
+ val areResolutionsEqual = expectedResolution == imageSize
+
+ assertThat(areRotationsEqual || areResolutionsEqual).isTrue()
+
+ // Delete captured image
+ scenario.withActivity { mCaptureResult?.delete() ?: Unit }
+ }
+ }
+
+ protected inline fun <reified A : CameraActivity> launchActivity(
+ lensFacing: Int,
+ captureMode: Int
+ ): ActivityScenario<A> {
+ val intent = Intent(
+ ApplicationProvider.getApplicationContext(),
+ A::class.java
+ ).apply {
+ putExtra(CameraActivity.KEY_LENS_FACING, lensFacing)
+ putExtra(CameraActivity.KEY_IMAGE_CAPTURE_MODE, captureMode)
+ }
+ return ActivityScenario.launch<A>(intent)
+ }
+
+ protected inline fun <reified A : CameraActivity> ActivityScenario<A>.waitOnCameraFrames() {
+ val analysisRunning = withActivity { mAnalysisRunning }
+ assertThat(analysisRunning.tryAcquire(IMAGES_COUNT, TIMEOUT, TimeUnit.SECONDS)).isTrue()
+ }
+
+ companion object {
+ protected const val IMAGES_COUNT = 30
+ protected const val TIMEOUT = 5L
+ @JvmStatic
+ protected val captureModes = arrayOf(
+ CameraActivity.IMAGE_CAPTURE_MODE_IN_MEMORY,
+ CameraActivity.IMAGE_CAPTURE_MODE_FILE,
+ CameraActivity.IMAGE_CAPTURE_MODE_OUTPUT_STREAM,
+ CameraActivity.IMAGE_CAPTURE_MODE_MEDIA_STORE
+ )
+ @JvmStatic
+ protected val lensFacing =
+ arrayOf(CameraSelector.LENS_FACING_BACK, CameraSelector.LENS_FACING_FRONT)
+ }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/LockedOrientationTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/LockedOrientationTest.kt
new file mode 100644
index 0000000..47c13ec
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/LockedOrientationTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.uiwidgets.rotations.imagecapture
+
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.integration.uiwidgets.rotations.LockedOrientationActivity
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.rule.GrantPermissionRule
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@LargeTest
+class LockedOrientationTest(
+ private val lensFacing: Int,
+ private val rotationDegrees: Int,
+ private val captureMode: Int
+) : ImageCaptureTest<LockedOrientationActivity>() {
+
+ companion object {
+ private val rotationDegrees = arrayOf(0, 90, 180, 270)
+ @JvmStatic
+ @Parameterized.Parameters(name = "lensFacing={0}, rotationDegrees={1}, captureMode={2}")
+ fun data() = mutableListOf<Array<Any?>>().apply {
+ lensFacing.forEach { lens ->
+ rotationDegrees.forEach { rotation ->
+ captureModes.forEach { mode ->
+ add(arrayOf(lens, rotation, mode))
+ }
+ }
+ }
+ }
+ }
+
+ @get:Rule
+ val mCameraPermissionRule: GrantPermissionRule =
+ GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
+
+ @Before
+ fun before() {
+ setUp(lensFacing)
+ }
+
+ @After
+ fun after() {
+ tearDown()
+ }
+
+ @Test
+ fun verifyRotation() {
+ verifyRotation<LockedOrientationActivity>(lensFacing, captureMode) {
+ rotate(rotationDegrees)
+ }
+ }
+
+ private fun ActivityScenario<LockedOrientationActivity>.rotate(rotationDegrees: Int) {
+ onActivity { activity ->
+ activity.mOrientationEventListener.onOrientationChanged(rotationDegrees)
+ }
+ }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/OrientationConfigChangesTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/OrientationConfigChangesTest.kt
new file mode 100644
index 0000000..a6a816b
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/OrientationConfigChangesTest.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.uiwidgets.rotations.imagecapture
+
+import android.view.Surface
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.integration.uiwidgets.rotations.OrientationConfigChangesOverriddenActivity
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.GrantPermissionRule
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.TimeUnit
+
+@RunWith(Parameterized::class)
+@LargeTest
+class OrientationConfigChangesTest(
+ private val lensFacing: Int,
+ private val rotation: Int,
+ private val captureMode: Int
+) : ImageCaptureTest<OrientationConfigChangesOverriddenActivity>() {
+
+ companion object {
+ private val rotations = arrayOf(
+ Surface.ROTATION_0,
+ Surface.ROTATION_90,
+ Surface.ROTATION_180,
+ Surface.ROTATION_270
+ )
+
+ @JvmStatic
+ @Parameterized.Parameters(name = "lensFacing={0}, rotation={1}, captureMode={2}")
+ fun data() = mutableListOf<Array<Any?>>().apply {
+ lensFacing.forEach { lens ->
+ rotations.forEach { rotation ->
+ captureModes.forEach { mode ->
+ add(arrayOf(lens, rotation, mode))
+ }
+ }
+ }
+ }
+ }
+
+ @get:Rule
+ val mCameraPermissionRule: GrantPermissionRule =
+ GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
+
+ @Before
+ fun before() {
+ setUp(lensFacing)
+ }
+
+ @After
+ fun after() {
+ tearDown()
+ }
+
+ @Test
+ fun verifyRotation() {
+ verifyRotation<OrientationConfigChangesOverriddenActivity>(
+ lensFacing,
+ captureMode
+ ) {
+ if (rotate(rotation)) {
+
+ // Wait for the rotation to occur
+ waitForRotation()
+ }
+ }
+ }
+
+ private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.rotate(rotation: Int):
+ Boolean {
+ val currentRotation = withActivity { this.display!!.rotation }
+ InstrumentationRegistry.getInstrumentation().uiAutomation.setRotation(rotation)
+ return currentRotation != rotation
+ }
+
+ private fun ActivityScenario<OrientationConfigChangesOverriddenActivity>.waitForRotation() {
+ val displayChanged = withActivity { mDisplayChanged }
+ assertThat(displayChanged.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+ }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/UnlockedOrientationTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/UnlockedOrientationTest.kt
new file mode 100644
index 0000000..d6e9f0c
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/rotations/imagecapture/UnlockedOrientationTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.uiwidgets.rotations.imagecapture
+
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import androidx.camera.integration.uiwidgets.rotations.CameraActivity
+import androidx.camera.integration.uiwidgets.rotations.UnlockedOrientationActivity
+import androidx.camera.integration.uiwidgets.rotations.UnlockedOrientationActivity.Companion.mCreated
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.rule.GrantPermissionRule
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.Semaphore
+import java.util.concurrent.TimeUnit
+
+@RunWith(Parameterized::class)
+@LargeTest
+class UnlockedOrientationTest(
+ private val lensFacing: Int,
+ private val orientation: Int,
+ private val captureMode: Int
+) : ImageCaptureTest<UnlockedOrientationActivity>() {
+
+ companion object {
+ val ORIENTATION_MAP = hashMapOf(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT to Configuration.ORIENTATION_PORTRAIT,
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT to Configuration.ORIENTATION_PORTRAIT,
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE to Configuration.ORIENTATION_LANDSCAPE,
+ ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE to Configuration.ORIENTATION_LANDSCAPE
+ )
+
+ @JvmStatic
+ @Parameterized.Parameters(name = "lensFacing={0}, orientation={1}, captureMode={2}")
+ fun data() = mutableListOf<Array<Any?>>().apply {
+ lensFacing.forEach { lens ->
+ ORIENTATION_MAP.keys.forEach { orientation ->
+ captureModes.forEach { mode ->
+ add(arrayOf(lens, orientation, mode))
+ }
+ }
+ }
+ }
+ }
+
+ @get:Rule
+ val mCameraPermissionRule: GrantPermissionRule =
+ GrantPermissionRule.grant(*CameraActivity.PERMISSIONS)
+
+ @Before
+ fun before() {
+ setUp(lensFacing)
+ }
+
+ @After
+ fun after() {
+ tearDown()
+ }
+
+ @Test
+ fun verifyRotation() {
+ verifyRotation<UnlockedOrientationActivity>(lensFacing, captureMode) {
+ if (rotate(orientation)) {
+
+ // Wait for the rotation to occur
+ waitForRotation()
+ }
+ }
+ }
+
+ private fun ActivityScenario<UnlockedOrientationActivity>.rotate(orientation: Int): Boolean {
+ val currentOrientation = withActivity { resources.configuration.orientation }
+ val didRotate = ORIENTATION_MAP[orientation] != currentOrientation
+ mCreated = Semaphore(0)
+ onActivity { activity ->
+ activity.requestedOrientation = orientation
+ }
+ return didRotate
+ }
+
+ private fun waitForRotation() {
+ assertThat(mCreated.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+ }
+}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml b/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml
index 3f58bb8..46c13d2 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/AndroidManifest.xml
@@ -39,5 +39,6 @@
</application>
<uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
index ac35c412..6e55523 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/CameraActivity.kt
@@ -23,6 +23,7 @@
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
+import android.util.Size
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.Camera
@@ -32,7 +33,6 @@
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
import androidx.camera.core.Preview
-import androidx.camera.core.impl.utils.Exif
import androidx.camera.core.impl.utils.executor.CameraXExecutors
import androidx.camera.integration.uiwidgets.R
import androidx.camera.lifecycle.ProcessCameraProvider
@@ -160,15 +160,15 @@
CameraXExecutors.mainThreadExecutor(),
object : ImageCapture.OnImageCapturedCallback() {
override fun onCaptureSuccess(image: ImageProxy) {
- mCapturedImageRotation = image.imageInfo.rotationDegrees
+ mCaptureResult = ImageCaptureResult.InMemory(image)
mCaptureDone.release()
- Log.d(TAG, "InMemory captured image rotation = $mCapturedImageRotation")
image.close()
+ Log.d(TAG, "MediaStore captured successful")
}
override fun onError(exception: ImageCaptureException) {
- Log.e(TAG, "InMemory capture failed", exception)
mCaptureDone.release()
+ Log.e(TAG, "InMemory capture failed", exception)
}
})
}
@@ -181,14 +181,14 @@
CameraXExecutors.mainThreadExecutor(),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
- mCapturedImageRotation = Exif.createFromFile(imageFile).rotation
+ mCaptureResult = ImageCaptureResult.FileOrOutputStream(imageFile)
mCaptureDone.release()
- Log.d(TAG, "File captured image rotation = $mCapturedImageRotation")
+ Log.d(TAG, "MediaStore captured successful")
}
override fun onError(exception: ImageCaptureException) {
- Log.e(TAG, "File capture failed", exception)
mCaptureDone.release()
+ Log.e(TAG, "File capture failed", exception)
}
})
}
@@ -202,14 +202,14 @@
CameraXExecutors.mainThreadExecutor(),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
- mCapturedImageRotation = Exif.createFromFile(imageFile).rotation
+ mCaptureResult = ImageCaptureResult.FileOrOutputStream(imageFile)
mCaptureDone.release()
- Log.d(TAG, "OutputStream captured image rotation = $mCapturedImageRotation")
+ Log.d(TAG, "MediaStore captured successful")
}
override fun onError(exception: ImageCaptureException) {
- Log.e(TAG, "OutputStream capture failed", exception)
mCaptureDone.release()
+ Log.e(TAG, "OutputStream capture failed", exception)
}
})
}
@@ -227,15 +227,15 @@
CameraXExecutors.mainThreadExecutor(),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
- val inputStream = contentResolver.openInputStream(outputFileResults.savedUri!!)
- mCapturedImageRotation = Exif.createFromInputStream(inputStream!!).rotation
+ mCaptureResult =
+ ImageCaptureResult.MediaStore(contentResolver, outputFileResults.savedUri!!)
mCaptureDone.release()
- Log.d(TAG, "MediaStore captured image rotation = $mCapturedImageRotation")
+ Log.d(TAG, "MediaStore captured successful")
}
override fun onError(exception: ImageCaptureException) {
- Log.e(TAG, "MediaStore capture failed", exception)
mCaptureDone.release()
+ Log.e(TAG, "MediaStore capture failed", exception)
}
})
}
@@ -259,14 +259,33 @@
val mCaptureDone = Semaphore(0)
@VisibleForTesting
- var mCapturedImageRotation = -1
- // Todo: Delete captured images when test finishes
+ var mCaptureResult: ImageCaptureResult? = null
@VisibleForTesting
fun getSensorRotationRelativeToAnalysisTargetRotation(): Int {
val targetRotation = mImageAnalysis.targetRotation
return mCamera.cameraInfo.getSensorRotationDegrees(targetRotation)
}
+
+ @VisibleForTesting
+ fun getSensorRotationRelativeToCaptureTargetRotation(): Int {
+ val targetRotation = mImageCapture.targetRotation
+ return mCamera.cameraInfo.getSensorRotationDegrees(targetRotation)
+ }
+
+ @Suppress("RestrictedApi")
+ @VisibleForTesting
+ fun getCaptureResolution(): Size {
+ val resolution = mImageCapture.attachedSurfaceResolution
+ ?: throw IllegalStateException("ImageCapture surface resolution is null")
+
+ val rotation = getSensorRotationRelativeToCaptureTargetRotation()
+ return if (rotation == 90 || rotation == 270) {
+ Size(resolution.height, resolution.width)
+ } else {
+ resolution
+ }
+ }
// endregion
companion object {
@@ -279,7 +298,7 @@
private const val TAG = "MainActivity"
private const val REQUEST_CODE_PERMISSIONS = 20
- private val PERMISSIONS =
- arrayOf(Manifest.permission.CAMERA)
+ val PERMISSIONS =
+ arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
}
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureResult.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureResult.kt
new file mode 100644
index 0000000..2dec4dd
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/rotations/ImageCaptureResult.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.integration.uiwidgets.rotations
+
+import android.content.ContentResolver
+import android.net.Uri
+import android.util.Size
+import androidx.camera.core.ImageProxy
+import androidx.camera.core.impl.utils.Exif
+import java.io.File
+
+/** A wrapper around an ImageCapture result, used for testing. */
+sealed class ImageCaptureResult {
+
+ abstract fun getResolution(): Size
+
+ abstract fun getRotation(): Int
+
+ abstract fun delete()
+
+ class InMemory(private val imageProxy: ImageProxy) : ImageCaptureResult() {
+ override fun getResolution() = Size(imageProxy.width, imageProxy.height)
+ override fun getRotation() = imageProxy.imageInfo.rotationDegrees
+ override fun delete() {}
+ }
+
+ class FileOrOutputStream(private val file: File) : ImageCaptureResult() {
+ private val exif = Exif.createFromFile(file)
+ override fun getResolution() = Size(exif.width, exif.height)
+ override fun getRotation() = exif.rotation
+ override fun delete() {
+ file.delete()
+ }
+ }
+
+ class MediaStore(private val contentResolver: ContentResolver, private val uri: Uri) :
+ ImageCaptureResult() {
+
+ private val exif: Exif
+
+ init {
+ val inputStream = contentResolver.openInputStream(uri)
+ exif = Exif.createFromInputStream(inputStream!!)
+ }
+
+ override fun getResolution() = Size(exif.width, exif.height)
+ override fun getRotation() = exif.rotation
+ override fun delete() {
+ contentResolver.delete(uri, null, null)
+ }
+ }
+}
\ No newline at end of file
diff --git a/collection/collection-benchmark/src/androidTest/AndroidManifest.xml b/collection/collection-benchmark/src/androidTest/AndroidManifest.xml
index 0e6ce1e..1664e8d 100644
--- a/collection/collection-benchmark/src/androidTest/AndroidManifest.xml
+++ b/collection/collection-benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/compose/compose-compiler-hosted/integration-tests/build.gradle b/compose/compose-compiler-hosted/integration-tests/build.gradle
index 8b77232..6cd123b 100644
--- a/compose/compose-compiler-hosted/integration-tests/build.gradle
+++ b/compose/compose-compiler-hosted/integration-tests/build.gradle
@@ -40,6 +40,7 @@
testImplementation(project(":ui:ui-core"))
testImplementation(project(":ui:ui-android-view"))
testImplementation(project(":compose:compose-compiler-hosted"))
+ testImplementation("androidx.core:core-ktx:1.1.0")
}
android {
@@ -65,6 +66,7 @@
tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = "1.8"
+ freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn"]
}
}
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt
index da5b3a2..d93f5ee 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenSignatureTest.kt
@@ -139,7 +139,7 @@
import androidx.compose.*
import android.widget.LinearLayout
import android.content.Context
- import androidx.ui.node.UiComposer
+ import androidx.ui.node.UiApplier
$src
@@ -150,12 +150,12 @@
private var __context: Context? = null
+ @OptIn(ExperimentalComposeApi::class)
fun makeComposer(): Composer<*> {
val container = LinearLayout(__context!!)
- return UiComposer(
- __context!!,
- container,
+ return Composer(
SlotTable(),
+ UiApplier(container),
Recomposer.current()
)
}
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt
index 7e7f8ff..320a230 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractCodegenTest.kt
@@ -116,6 +116,80 @@
if (dumpClasses) dumpClasses(loader)
}
+ protected val COMPOSE_VIEW_STUBS_IMPORTS = """
+ import android.view.View
+ import android.widget.TextView
+ import android.widget.Button
+ import android.view.Gravity
+ import android.widget.LinearLayout
+ import androidx.compose.Composable
+ import androidx.ui.viewinterop.emitView
+ """.trimIndent()
+
+ protected val COMPOSE_VIEW_STUBS = """
+ @Composable
+ fun TextView(
+ id: Int = 0,
+ gravity: Int = Gravity.TOP or Gravity.START,
+ text: String = "",
+ onClick: (() -> Unit)? = null,
+ onClickListener: View.OnClickListener? = null
+ ) {
+ emitView(::TextView) {
+ if (id != 0) it.id = id
+ it.text = text
+ it.gravity = gravity
+ if (onClickListener != null) it.setOnClickListener(onClickListener)
+ if (onClick != null) it.setOnClickListener(View.OnClickListener { onClick() })
+ }
+ }
+
+ @Composable
+ fun Button(
+ id: Int = 0,
+ text: String = "",
+ onClick: (() -> Unit)? = null,
+ onClickListener: View.OnClickListener? = null
+ ) {
+ emitView(::Button) {
+ if (id != 0) it.id = id
+ it.text = text
+ if (onClickListener != null) it.setOnClickListener(onClickListener)
+ if (onClick != null) it.setOnClickListener(View.OnClickListener { onClick() })
+ }
+ }
+
+ @Composable
+ fun LinearLayout(
+ id: Int = 0,
+ orientation: Int = LinearLayout.VERTICAL,
+ onClickListener: View.OnClickListener? = null,
+ children: @Composable () -> Unit
+ ) {
+ emitView(
+ ::LinearLayout,
+ {
+ if (id != 0) it.id = id
+ if (onClickListener != null) it.setOnClickListener(onClickListener)
+ it.orientation = orientation
+ },
+ children
+ )
+ }
+ """.trimIndent()
+
+ protected fun testCompileWithViewStubs(source: String, dumpClasses: Boolean = false) =
+ testCompile(
+ """
+ $COMPOSE_VIEW_STUBS_IMPORTS
+
+ $source
+
+ $COMPOSE_VIEW_STUBS
+ """,
+ dumpClasses
+ )
+
protected fun testCompileEmittable(source: String, dumpClasses: Boolean = false) = testCompile(
"""
@file:OptIn(
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt
index 81cd9d8..6e62935 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractIrTransformTest.kt
@@ -83,18 +83,18 @@
) {
"${it.groupValues[1]}<>"
}
- // restartableFunctionInstance(<>, true)
+ // composableLambdaInstance(<>, true)
.replace(
Regex(
- "(restartableFunctionInstance\\()([-\\d]+)"
+ "(composableLambdaInstance\\()([-\\d]+)"
)
) {
"${it.groupValues[1]}<>"
}
- // restartableFunction(%composer, <>, true)
+ // composableLambda(%composer, <>, true)
.replace(
Regex(
- "(restartableFunction\\(%composer,\\s)([-\\d]+)"
+ "(composableLambda\\(%composer,\\s)([-\\d]+)"
)
) {
"${it.groupValues[1]}<>"
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt
index a5b9329..5cd2dbb 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/AbstractLoweringTests.kt
@@ -16,8 +16,9 @@
package androidx.compose.plugins.kotlin
+import android.view.View
import androidx.compose.Composer
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
+import org.robolectric.RuntimeEnvironment
import java.net.URLClassLoader
abstract class AbstractLoweringTests : AbstractCodegenTest() {
@@ -28,12 +29,25 @@
import android.content.Context
import android.widget.*
import androidx.compose.*
+ $COMPOSE_VIEW_STUBS_IMPORTS
$text
+ $COMPOSE_VIEW_STUBS
+
""", dumpClasses)
}
+ @Suppress("UNCHECKED_CAST")
+ fun View.getComposedSet(tagId: Int): Set<String>? = getTag(tagId) as? Set<String>
+
+ protected fun execute(block: () -> Unit) {
+ val scheduler = RuntimeEnvironment.getMasterScheduler()
+ scheduler.pause()
+ block()
+ scheduler.advanceToLastPostedRunnable()
+ }
+
fun codegenNoImports(text: String, dumpClasses: Boolean = false) {
val className = "Test_${uniqueNumber++}"
val fileName = "$className.kt"
@@ -64,11 +78,12 @@
val compiledClasses = classLoader(
"""
- import android.content.Context
import android.widget.*
import androidx.compose.*
import androidx.ui.androidview.adapters.*
+ $COMPOSE_VIEW_STUBS_IMPORTS
+
$supportingCode
class $className {
@@ -78,6 +93,8 @@
$composeCode
}
}
+
+ $COMPOSE_VIEW_STUBS
""", fileName, dumpClasses
)
@@ -112,23 +129,7 @@
return compose { composer, _, _ ->
val values = valuesFactory()
val arguments = values.map { it.value }.toTypedArray()
- testMethod.invoke(instanceOfClass, *arguments, composer, 0, 0)
+ testMethod.invoke(instanceOfClass, *arguments, composer, 0, 1)
}
}
-
- private fun ResolvedCall<*>.isEmit(): Boolean = candidateDescriptor is ComposableEmitDescriptor
- private fun ResolvedCall<*>.isCall(): Boolean =
- candidateDescriptor is ComposableFunctionDescriptor
-
- private val callPattern = Regex("(<normal>)|(<emit>)|(<call>)")
- private fun extractCarets(text: String): Pair<String, List<Pair<Int, String>>> {
- val indices = mutableListOf<Pair<Int, String>>()
- var offset = 0
- val src = callPattern.replace(text) {
- indices.add(it.range.first - offset to it.value)
- offset += it.range.last - it.range.first + 1
- ""
- }
- return src to indices
- }
}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt
index b660a32d..ca93902 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallLoweringTests.kt
@@ -21,11 +21,6 @@
import android.widget.TextView
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
-import org.jetbrains.kotlin.psi.KtCallExpression
-import org.jetbrains.kotlin.psi.KtFile
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@@ -253,10 +248,7 @@
fun testReceiverLambdaInvocation(): Unit = ensureSetup {
codegen(
"""
- import androidx.compose.*
- import androidx.ui.node.UiComposer
-
- class TextSpanScope internal constructor(val composer: UiComposer)
+ class TextSpanScope
@Composable fun TextSpanScope.Foo(children: @Composable TextSpanScope.() -> Unit) {
children()
@@ -291,7 +283,6 @@
codegen(
"""
import androidx.compose.*
- import android.widget.LinearLayout
@Composable
inline fun PointerInputWrapper(
@@ -311,12 +302,12 @@
codegenNoImports(
"""
import androidx.compose.Composable
- import android.widget.LinearLayout
+
+ @Composable fun Wrap(content: @Composable () -> Unit) { content() }
@Composable
fun Foo() {
- // emits work
- LinearLayout {
+ Wrap {
// nested calls work
Bar()
}
@@ -326,7 +317,6 @@
@Composable
fun Bar() {}
-
""".trimIndent()
)
}
@@ -374,47 +364,6 @@
}
@Test
- fun testSetViewContentIssue(): Unit = ensureSetup {
- codegen(
- """
- import android.app.Activity
- import android.os.Bundle
- import android.view.Gravity
- import android.view.ViewGroup
- import android.widget.*
- import androidx.compose.*
- import androidx.ui.core.setViewContent
- import androidx.ui.androidview.adapters.*
-
- class RippleActivity : Activity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setViewContent {
- val layoutParams = LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- 0,
- 1f
- )
- val gravity = Gravity.CENTER_HORIZONTAL
- LinearLayout(orientation = LinearLayout.VERTICAL) {
- TextView(gravity = gravity, text = "Compose card with ripple:")
- LinearLayout(layoutParams = layoutParams) {
- // RippleDemo()
- }
- TextView(gravity = gravity, text = "Platform button with ripple:")
- LinearLayout(layoutParams = layoutParams, padding = 50.dp) {
- // Button(background = getDrawable(R.drawable.ripple))
- }
- }
- }
- }
- }
- """
- )
- }
-
- @Test
fun testGenericParameterOrderIssue(): Unit = ensureSetup {
codegen(
"""
@@ -472,37 +421,6 @@
}
@Test
- fun testWebViewBug(): Unit = ensureSetup {
- codegen(
- """
-import android.webkit.WebView
-import android.webkit.WebViewClient
-import androidx.compose.Composable
-
-class WebContext {
- var webView: WebView? = null
-}
-
-private fun WebView.setRef(ref: (WebView) -> Unit) {
- ref(this)
-}
-
-@Composable
-fun WebComponent(
- url: String,
- webViewClient: WebViewClient = WebViewClient(),
- webContext: WebContext
-) {
-
- WebView(
- ref = { webContext.webView = it }
- )
-}
- """
- )
- }
-
- @Test
fun testStuffThatIWantTo(): Unit = ensureSetup {
codegen(
"""
@@ -543,7 +461,6 @@
fun testSimpleClassResolution(): Unit = ensureSetup {
compose(
"""
- import android.widget.TextView
import androidx.compose.*
@Composable
@@ -596,9 +513,7 @@
fun testObservable(): Unit = ensureSetup {
compose(
"""
- import android.widget.Button
import androidx.compose.*
- import androidx.ui.androidview.adapters.setOnClick
@Composable
fun SimpleComposable() {
@@ -981,27 +896,6 @@
}
@Test
- fun testInliningTemp(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(x: Double, children: @Composable Double.() -> Unit) {
- x.children()
- }
- """,
- """
- Foo(x=1.0) {
- TextView(text=this.toString(), id=123)
- }
- """,
- { mapOf("foo" to "bar") }
- ).then { activity ->
- val textView = activity.findViewById(123) as TextView
- assertEquals("1.0", textView.text)
- }
- }
-
- @Test
fun testInliningTemp2(): Unit = ensureSetup {
compose(
"""
@@ -1148,33 +1042,1542 @@
)
}
- private fun ResolvedCall<*>.isEmit(): Boolean = candidateDescriptor is ComposableEmitDescriptor
- private fun ResolvedCall<*>.isCall(): Boolean =
- candidateDescriptor is ComposableFunctionDescriptor
+ @Test
+ fun testReturnValue(): Unit = ensureSetup {
+ compose("""
+ var a = 0
+ var b = 0
- private val callPattern = Regex("(<normal>)|(<emit>)|(<call>)")
- private fun extractCarets(text: String): Pair<String, List<Pair<Int, String>>> {
- val indices = mutableListOf<Pair<Int, String>>()
- var offset = 0
- val src = callPattern.replace(text) {
- indices.add(it.range.first - offset to it.value)
- offset += it.range.last - it.range.first + 1
- ""
+ @Composable
+ fun SimpleComposable() {
+ a++
+ val c = state { 0 }
+ val d = remember(c.value) { b++; b }
+ val recompose = invalidate
+ Button(
+ text=listOf(a, b, c.value, d).joinToString(", "),
+ onClick={ c.value += 1 },
+ id=42
+ )
+ Button(
+ text="Recompose",
+ onClick={ recompose() },
+ id=43
+ )
+ }
+ """,
+ "SimpleComposable()",
+ noParameters
+ ).then { activity ->
+ val button = activity.findViewById(42) as Button
+ assertEquals(
+ button.text,
+ listOf(
+ 1, // SimpleComposable has run once
+ 1, // memo has been called once because of initial mount
+ 0, // state was in itialized at 0
+ 1 // memo should return b
+ ).joinToString(", ")
+ )
+ button.performClick()
+ }.then { activity ->
+ val button = activity.findViewById(42) as Button
+ val recompose = activity.findViewById(43) as Button
+ assertEquals(
+ button.text,
+ listOf(
+ 2, // SimpleComposable has run twice
+ 2, // memo has been called twice, because state input has changed
+ 1, // state was changed to 1
+ 2 // memo should return b
+ ).joinToString(", ")
+ )
+ recompose.performClick()
+ }.then { activity ->
+ val button = activity.findViewById(42) as Button
+ assertEquals(
+ button.text,
+ listOf(
+ 3, // SimpleComposable has run three times
+ 2, // memo was not called this time, because input didn't change
+ 1, // state stayed at 1
+ 2 // memo should return b
+ ).joinToString(", ")
+ )
}
- return src to indices
}
- private fun resolvedCallAtOffset(
- bindingContext: BindingContext,
- jetFile: KtFile,
- index: Int
- ): ResolvedCall<*>? {
- val element = jetFile.findElementAt(index)!!
- val callExpression = element.parentOfType<KtCallExpression>()
- return callExpression?.getResolvedCall(bindingContext)
+ @Test
+ fun testReorderedArgsReturnValue(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable
+ fun SimpleComposable() {
+ val x = remember(calculation = { "abc" }, v1 = "def")
+ TextView(
+ text=x,
+ id=42
+ )
+ }
+ """,
+ "SimpleComposable()",
+ noParameters
+ ).then { activity ->
+ val button = activity.findViewById(42) as TextView
+ assertEquals(button.text, "abc")
+ }
+ }
+
+ @Test
+ fun testTrivialReturnValue(): Unit = ensureSetup {
+ compose("""
+ @Composable
+ fun <T> identity(value: T): T = value
+
+ @Composable
+ fun SimpleComposable() {
+ val x = identity("def")
+ TextView(
+ text=x,
+ id=42
+ )
+ }
+ """,
+ "SimpleComposable()",
+ noParameters
+ ).then { activity ->
+ val button = activity.findViewById(42) as TextView
+ assertEquals(button.text, "def")
+ }
+ }
+
+ @Test
+ fun testForDevelopment(): Unit = ensureSetup {
+ codegen(
+ """
+ import androidx.compose.*
+
+ @Composable
+ fun bar() {
+
+ }
+
+ @Composable
+ fun foo() {
+ TextView(text="Hello World")
+ }
+ """
+ )
+ }
+
+ @Test
+ fun testInliningTemp(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable
+ fun Foo(x: Double, children: @Composable Double.() -> Unit) {
+ x.children()
+ }
+ """,
+ """
+ Foo(x=1.0) {
+ TextView(text=this.toString(), id=123)
+ }
+ """,
+ { mapOf("foo" to "bar") }
+ ).then { activity ->
+ val textView = activity.findViewById(123) as TextView
+ assertEquals("1.0", textView.text)
+ }
+ }
+
+ @Test
+ fun testCGUpdatedComposition(): Unit = ensureSetup {
+ var value = "Hello, world!"
+
+ compose(
+ """""",
+ """
+ TextView(text=value, id=42)
+ """,
+ { mapOf("value" to value) }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+
+ value = "Other value"
+ }.then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Other value", textView.text)
+ }
+ }
+
+ @Test
+ fun testCGNUpdatedComposition(): Unit = ensureSetup {
+ var value = "Hello, world!"
+
+ compose(
+ """""",
+ """
+ TextView(text=value, id=42)
+ """,
+ { mapOf("value" to value) }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+
+ value = "Other value"
+ }.then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Other value", textView.text)
+ }
+ }
+
+ @Test
+ fun testCGViewGroup(): Unit = ensureSetup {
+ val tvId = 258
+ val llId = 260
+ var text = "Hello, world!"
+ var orientation = LinearLayout.HORIZONTAL
+
+ compose(
+ """""",
+ """
+ LinearLayout(orientation=orientation, id=$llId) {
+ TextView(text=text, id=$tvId)
+ }
+ """,
+ { mapOf("text" to text, "orientation" to orientation) }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val linearLayout = activity.findViewById(llId) as LinearLayout
+
+ assertEquals(text, textView.text)
+ assertEquals(orientation, linearLayout.orientation)
+
+ text = "Other value"
+ orientation = LinearLayout.VERTICAL
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val linearLayout = activity.findViewById(llId) as LinearLayout
+
+ assertEquals(text, textView.text)
+ assertEquals(orientation, linearLayout.orientation)
+ }
+ }
+
+ @Test
+ fun testCGNFunctionComponent(): Unit = ensureSetup {
+ var text = "Hello, world!"
+ val tvId = 123
+
+ compose(
+ """
+ @Composable
+ fun Foo(text: String) {
+ TextView(id=$tvId, text=text)
+ }
+
+ """,
+ """
+ Foo(text=text)
+ """,
+ { mapOf("text" to text) }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+
+ assertEquals(text, textView.text)
+ text = "wat"
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+
+ assertEquals(text, textView.text)
+ }
+ }
+
+ @Test
+ fun testAmbientConsumedFromDefaultParameter(): Unit = ensureSetup {
+ val initialText = "no text"
+ val helloWorld = "Hello World!"
+ compose("""
+ val TextAmbient = ambientOf { "$initialText" }
+
+ @Composable
+ fun Main() {
+ var text = state { "$initialText" }
+ Providers(TextAmbient provides text.value) {
+ LinearLayout {
+ ConsumesAmbientFromDefaultParameter()
+ Button(
+ text = "Change ambient value",
+ onClick={ text.value = "$helloWorld" },
+ id=101
+ )
+ }
+ }
+ }
+
+ @Composable
+ fun ConsumesAmbientFromDefaultParameter(text: String = TextAmbient.current) {
+ TextView(text = text, id = 42)
+ }
+ """,
+ "Main()",
+ noParameters
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals(initialText, textView.text)
+ }.then { activity ->
+ val button = activity.findViewById(101) as Button
+ button.performClick()
+ }
+ .then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals(helloWorld, textView.text)
+ }
+ }
+
+ @Test
+ fun testCGNViewGroup(): Unit = ensureSetup {
+ val tvId = 258
+ val llId = 260
+ var text = "Hello, world!"
+ var orientation = LinearLayout.HORIZONTAL
+
+ compose(
+ """""",
+ """
+ LinearLayout(orientation=orientation, id=$llId) {
+ TextView(text=text, id=$tvId)
+ }
+ """,
+ { mapOf("text" to text, "orientation" to orientation) }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val linearLayout = activity.findViewById(llId) as LinearLayout
+
+ assertEquals(text, textView.text)
+ assertEquals(orientation, linearLayout.orientation)
+
+ text = "Other value"
+ orientation = LinearLayout.VERTICAL
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val linearLayout = activity.findViewById(llId) as LinearLayout
+
+ assertEquals(text, textView.text)
+ assertEquals(orientation, linearLayout.orientation)
+ }
+ }
+
+ @Test
+ fun testMemoization(): Unit = ensureSetup {
+ val tvId = 258
+ val tagId = (3 shl 24) or "composed_set".hashCode()
+
+ compose(
+ """
+ var composedSet = mutableSetOf<String>()
+ var inc = 1
+
+ @Composable fun ComposedTextView(id: Int, composed: Set<String>) {
+ emitView(::TextView) {
+ it.id = id
+ it.setTag($tagId, composed)
+ }
+ }
+
+ @Composable fun ComposePrimitive(value: Int) {
+ composedSet.add("ComposePrimitive(" + value + ")")
+ }
+
+ class MutableThing(var value: String)
+
+ val constantMutableThing = MutableThing("const")
+
+ @Composable fun ComposeMutable(value: MutableThing) {
+ composedSet.add("ComposeMutable(" + value.value + ")")
+ }
+ """,
+ """
+ composedSet.clear()
+
+ ComposePrimitive(value=123)
+ ComposePrimitive(value=inc)
+ ComposeMutable(value=constantMutableThing)
+ ComposeMutable(value=MutableThing("new"))
+
+ ComposedTextView(id=$tvId, composed=composedSet)
+
+ inc++
+ """,
+ { mapOf("text" to "") }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val composedSet = textView.getComposedSet(tagId) ?: error(
+ "expected a compose set to exist")
+
+ fun assertContains(contains: Boolean, key: String) {
+ assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
+ }
+
+ assertContains(true, "ComposePrimitive(123)")
+ assertContains(true, "ComposePrimitive(1)")
+ assertContains(true, "ComposeMutable(const)")
+ assertContains(true, "ComposeMutable(new)")
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val composedSet = textView.getComposedSet(tagId)
+ ?: error("expected a compose set to exist")
+
+ fun assertContains(contains: Boolean, key: String) {
+ assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
+ }
+
+ // the primitive component skips based on equality
+ assertContains(false, "ComposePrimitive(123)")
+
+ // since the primitive changed, this one recomposes again
+ assertContains(true, "ComposePrimitive(2)")
+
+ // since this is a potentially mutable object, we don't skip based on it
+ assertContains(true, "ComposeMutable(const)")
+
+ // since it's a new one every time, we definitely don't skip
+ assertContains(true, "ComposeMutable(new)")
+ }
+ }
+
+ @Test
+ fun testInlineClassMemoization(): Unit = ensureSetup {
+ val tvId = 258
+ val tagId = (3 shl 24) or "composed_set".hashCode()
+
+ compose(
+ """
+ inline class InlineInt(val value: Int)
+ inline class InlineInlineInt(val value: InlineInt)
+ inline class InlineMutableSet(val value: MutableSet<String>)
+ @Composable fun ComposedTextView(id: Int, composed: Set<String>) {
+ emitView(::TextView) {
+ it.id = id
+ it.setTag($tagId, composed)
+ }
+ }
+
+ val composedSet = mutableSetOf<String>()
+ val constInlineInt = InlineInt(0)
+ var inc = 2
+ val constInlineMutableSet = InlineMutableSet(mutableSetOf("a"))
+
+ @Composable fun ComposedInlineInt(value: InlineInt) {
+ composedSet.add("ComposedInlineInt(" + value + ")")
+ }
+
+ @Composable fun ComposedInlineInlineInt(value: InlineInlineInt) {
+ composedSet.add("ComposedInlineInlineInt(" + value + ")")
+ }
+
+ @Composable fun ComposedInlineMutableSet(value: InlineMutableSet) {
+ composedSet.add("ComposedInlineMutableSet(" + value + ")")
+ }
+ """,
+ """
+ composedSet.clear()
+
+ ComposedInlineInt(constInlineInt)
+ ComposedInlineInt(InlineInt(1))
+ ComposedInlineInt(InlineInt(inc))
+ ComposedInlineInlineInt(InlineInlineInt(InlineInt(2)))
+ ComposedInlineMutableSet(constInlineMutableSet)
+
+ ComposedTextView(id=$tvId, composed=composedSet)
+
+ inc++
+ """,
+ { mapOf("text" to "") }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val composedSet = textView.getComposedSet(tagId)
+ ?: error("expected a compose set to exist")
+
+ // All composables should execute since it's the first time.
+ assert(composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
+ assert(composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
+ assert(composedSet.contains("ComposedInlineInt(InlineInt(value=2))"))
+ assert(composedSet.contains(
+ "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
+ assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val composedSet = textView.getComposedSet(tagId)
+ ?: error("expected a compose set to exist")
+
+ // InlineInt and InlineInlineInt are stable, so the corresponding composables should
+ // not run for values equal to previous compositions.
+ assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
+ assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
+ assert(!composedSet.contains(
+ "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
+
+ // But if a stable composable is passed a new value, it should re-run.
+ assert(composedSet.contains("ComposedInlineInt(InlineInt(value=3))"))
+
+ // And composables for inline classes with non-stable underlying types should run.
+ assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
+ }
+ }
+
+ @Test
+ fun testStringParameterMemoization(): Unit = ensureSetup {
+ val tvId = 258
+ val tagId = (3 shl 24) or "composed_set".hashCode()
+
+ compose(
+ """
+ @Composable fun ComposedTextView(id: Int, composed: Set<String>) {
+ emitView(::TextView) {
+ it.id = id
+ it.setTag($tagId, composed)
+ }
+ }
+
+ val composedSet = mutableSetOf<String>()
+ val FOO = "foo"
+
+ @Composable fun ComposedString(value: String) {
+ composedSet.add("ComposedString(" + value + ")")
+ }
+ """,
+ """
+ composedSet.clear()
+
+ ComposedString(FOO)
+ ComposedString("bar")
+
+ ComposedTextView(id=$tvId, composed=composedSet)
+ """,
+ { mapOf("text" to "") }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val composedSet = textView.getComposedSet(tagId)
+ ?: error("expected a compose set to exist")
+
+ // All composables should execute since it's the first time.
+ assert(composedSet.contains("ComposedString(foo)"))
+ assert(composedSet.contains("ComposedString(bar)"))
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ val composedSet = textView.getComposedSet(tagId)
+ ?: error("expected a compose set to exist")
+
+ assert(composedSet.isEmpty())
+ }
+ }
+
+ @Test
+ fun testCGNSimpleCall(): Unit = ensureSetup {
+ val tvId = 258
+ var text = "Hello, world!"
+
+ compose(
+ """
+ @Composable fun SomeFun(x: String) {
+ TextView(text=x, id=$tvId)
+ }
+ """,
+ """
+ SomeFun(x=text)
+ """,
+ { mapOf("text" to text) }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+
+ assertEquals(text, textView.text)
+
+ text = "Other value"
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+
+ assertEquals(text, textView.text)
+ }
+ }
+
+ @Test
+ fun testCGNCallWithChildren(): Unit = ensureSetup {
+ val tvId = 258
+ var text = "Hello, world!"
+
+ compose(
+ """
+ @Composable
+ fun Block(children: @Composable () -> Unit) {
+ children()
+ }
+ """,
+ """
+ Block {
+ Block {
+ TextView(text=text, id=$tvId)
+ }
+ }
+ """,
+ { mapOf("text" to text) }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+
+ assertEquals(text, textView.text)
+
+ text = "Other value"
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+
+ assertEquals(text, textView.text)
+ }
+ }
+
+ @Test
+ fun testCGComposableFunctionInvocationOneParameter(): Unit = ensureSetup {
+ val tvId = 91
+ var phone = "(123) 456-7890"
+ compose(
+ """
+ @Composable
+ fun Phone(value: String) {
+ TextView(text=value, id=$tvId)
+ }
+ """,
+ """
+ Phone(value=phone)
+ """,
+ { mapOf("phone" to phone) }
+ ).then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ assertEquals(phone, textView.text)
+
+ phone = "(123) 456-7899"
+ }.then { activity ->
+ val textView = activity.findViewById(tvId) as TextView
+ assertEquals(phone, textView.text)
+ }
+ }
+
+ @Test
+ fun testCGComposableFunctionInvocationTwoParameters(): Unit = ensureSetup {
+ val tvId = 111
+ val rsId = 112
+ var left = 0
+ var right = 0
+ compose(
+ """
+ var addCalled = 0
+
+ @Composable
+ fun AddView(left: Int, right: Int) {
+ addCalled++
+ TextView(text="${'$'}left + ${'$'}right = ${'$'}{left + right}", id=$tvId)
+ TextView(text="${'$'}addCalled", id=$rsId)
+ }
+ """, """
+ AddView(left=left, right=right)
+ """,
+ { mapOf("left" to left, "right" to right) }
+ ).then { activity ->
+ // Should be called on the first compose
+ assertEquals("1", (activity.findViewById(rsId) as TextView).text)
+ assertEquals(
+ "$left + $right = ${left + right}",
+ (activity.findViewById(tvId) as TextView).text
+ )
+ }.then { activity ->
+ // Should be skipped on the second compose
+ assertEquals("1", (activity.findViewById(rsId) as TextView).text)
+ assertEquals(
+ "$left + $right = ${left + right}",
+ (activity.findViewById(tvId) as TextView).text
+ )
+
+ left = 1
+ }.then { activity ->
+ // Should be called again because left changed.
+ assertEquals("2", (activity.findViewById(rsId) as TextView).text)
+ assertEquals(
+ "$left + $right = ${left + right}",
+ (activity.findViewById(tvId) as TextView).text
+ )
+
+ right = 41
+ }.then { activity ->
+ // Should be called again because right changed
+ assertEquals("3", (activity.findViewById(rsId) as TextView).text)
+ assertEquals(
+ "$left + $right = ${left + right}",
+ (activity.findViewById(tvId) as TextView).text
+ )
+ }.then { activity ->
+ // Should be skipped because nothing changed
+ assertEquals("3", (activity.findViewById(rsId) as TextView).text)
+ }
+ }
+
+ @Test
+ fun testImplicitReceiverPassing1(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable fun Int.Foo(x: @Composable Int.() -> Unit) {
+ x()
+ }
+ """,
+ """
+ val id = 42
+
+ id.Foo(x={
+ TextView(text="Hello, world!", id=this)
+ })
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ @Test
+ fun testImplicitReceiverPassing2(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable fun Int.Foo(x: @Composable Int.(text: String) -> Unit, text: String) {
+ x(text=text)
+ }
+
+ @Composable fun MyText(text: String, id: Int) {
+ TextView(text=text, id=id)
+ }
+ """,
+ """
+ val id = 42
+
+ id.Foo(text="Hello, world!", x={ text ->
+ MyText(text=text, id=this)
+ })
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ @Test
+ fun testEffects1(): Unit = ensureSetup {
+ compose(
+ """
+ import androidx.ui.androidview.adapters.*
+
+ @Composable
+ fun Counter() {
+ var count = state { 0 }
+ TextView(
+ text=("Count: " + count.value),
+ onClick={
+ count.value += 1
+ },
+ id=42
+ )
+ }
+ """,
+ """
+ Counter()
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Count: 0", textView.text)
+ textView.performClick()
+ }.then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Count: 1", textView.text)
+ }
+ }
+
+ @Test
+ fun testEffects2(): Unit = ensureSetup {
+ compose(
+ """
+ import androidx.ui.androidview.adapters.*
+
+ @Composable
+ fun Counter() {
+ var count = state { 0 }
+ TextView(
+ text=("Count: " + count.value),
+ onClick={
+ count.value += 1
+ },
+ id=42
+ )
+ }
+ """,
+ """
+ Counter()
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Count: 0", textView.text)
+ textView.performClick()
+ }.then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Count: 1", textView.text)
+ }
+ }
+
+ @Test
+ fun testEffects3(): Unit = ensureSetup {
+ val log = StringBuilder()
+ compose(
+ """
+ import androidx.ui.androidview.adapters.*
+
+ @Composable
+ fun Counter(log: StringBuilder) {
+ var count = state { 0 }
+ onCommit {
+ log.append("a")
+ }
+ onActive {
+ log.append("b")
+ }
+ TextView(
+ text=("Count: " + count.value),
+ onClick={
+ count.value += 1
+ },
+ id=42
+ )
+ }
+ """,
+ """
+ Counter(log=log)
+ """,
+ { mapOf("log" to log) }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Count: 0", textView.text)
+ assertEquals("ab", log.toString())
+
+ execute {
+ textView.performClick()
+ }
+
+ assertEquals("Count: 1", textView.text)
+ assertEquals("aba", log.toString())
+ }
+ }
+
+ @Test
+ fun testEffects4(): Unit = ensureSetup {
+ val log = StringBuilder()
+ compose(
+ """
+ import androidx.ui.androidview.adapters.*
+
+ @Composable
+ fun printer(log: StringBuilder, str: String) {
+ onCommit {
+ log.append(str)
+ }
+ }
+
+ @Composable
+ fun Counter(log: StringBuilder) {
+ var count = state { 0 }
+ printer(log, "" + count.value)
+ TextView(
+ text=("Count: " + count.value),
+ onClick={
+ count.value += 1
+ },
+ id=42
+ )
+ }
+ """,
+ """
+ Counter(log=log)
+ """,
+ { mapOf("log" to log) }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Count: 0", textView.text)
+ assertEquals("0", log.toString())
+
+ execute {
+ textView.performClick()
+ }
+
+ assertEquals("Count: 1", textView.text)
+ assertEquals("01", log.toString())
+ }
+ }
+
+ @Test
+ fun testVariableCalls1(): Unit = ensureSetup {
+ compose(
+ """
+ val component = @Composable {
+ TextView(text="Hello, world!", id=42)
+ }
+ """,
+ """
+ component()
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ @Test
+ fun testVariableCalls2(): Unit = ensureSetup {
+ compose(
+ """
+ val component = @Composable {
+ TextView(text="Hello, world!", id=42)
+ }
+ class HolderA(val composable: @Composable () -> Unit)
+
+ val holder = HolderA(component)
+
+ """,
+ """
+ holder.composable()
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ @Test
+ fun testVariableCalls3(): Unit = ensureSetup {
+ compose(
+ """
+ val component = @Composable {
+ TextView(text="Hello, world!", id=42)
+ }
+ class HolderB(val composable: @Composable () -> Unit) {
+ @Composable
+ fun Foo() {
+ composable()
+ }
+ }
+
+ val holder = HolderB(component)
+
+ """,
+ """
+ holder.Foo()
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ // b/123721921
+ @Test
+ fun testDefaultParameters1(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable
+ fun Foo(a: Int = 42, b: String) {
+ TextView(text=b, id=a)
+ }
+ """,
+ """
+ Foo(b="Hello, world!")
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ @Test
+ fun testDefaultParameters2(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable
+ fun Foo(a: Int = 42, b: String, c: @Composable () -> Unit) {
+ c()
+ TextView(text=b, id=a)
+ }
+ """,
+ """
+ Foo(b="Hello, world!") {}
+ """,
+ { mapOf<String, String>() }
+ ).then { activity ->
+ val textView = activity.findViewById(42) as TextView
+ assertEquals("Hello, world!", textView.text)
+ }
+ }
+
+ @Test
+ fun testMovement(): Unit = ensureSetup {
+ val tvId = 50
+ val btnIdAdd = 100
+ val btnIdUp = 200
+ val btnIdDown = 300
+
+ // Duplicate the steps to reproduce an issue discovered in the Reorder example
+ compose(
+ """
+ fun <T> List<T>.move(from: Int, to: Int): List<T> {
+ if (to < from) return move(to, from)
+ val item = get(from)
+ val currentItem = get(to)
+ val left = if (from > 0) subList(0, from) else emptyList()
+ val right = if (to < size) subList(to + 1, size) else emptyList()
+ val middle = if (to - from > 1) subList(from + 1, to) else emptyList()
+ return left + listOf(currentItem) + middle + listOf(item) + right
+ }
+
+ @Composable
+ fun Reordering() {
+ val items = state { listOf(1, 2, 3, 4, 5) }
+
+ LinearLayout(orientation=LinearLayout.VERTICAL) {
+ items.value.forEachIndexed { index, id ->
+ key(id) {
+ Item(
+ id=id,
+ onMove={ amount ->
+ val next = index + amount
+ if (next >= 0 && next < items.value.size) {
+ items.value = items.value.move(index, index + amount)
+ }
+ }
+ )
+ }
+ }
+ }
+ }
+
+ @Composable
+ // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
+ fun Item(id: Int, onMove: (Int) -> Unit) {
+ val count = state { 0 }
+ LinearLayout(orientation=LinearLayout.HORIZONTAL) {
+ TextView(id=(id+$tvId), text="id: ${'$'}id amt: ${'$'}{count.value}")
+ Button(id=(id+$btnIdAdd), text="+", onClick={ count.value++ })
+ Button(id=(id+$btnIdUp), text="Up", onClick={ onMove(1) })
+ Button(id=(id+$btnIdDown), text="Down", onClick={ onMove(-1) })
+ }
+ }
+ """,
+ """
+ Reordering()
+ """, noParameters
+ ).then { activity ->
+ // Click 5 add
+ val button = activity.findViewById(btnIdAdd + 5) as Button
+ button.performClick()
+ }.then { activity ->
+ // Click 5 down
+ val button = activity.findViewById(btnIdDown + 5) as Button
+ button.performClick()
+ }.then { activity ->
+ // Click 5 down
+ val button = activity.findViewById(btnIdDown + 5) as Button
+ button.performClick()
+ }.then { activity ->
+ // Click 5 up
+ val button = activity.findViewById(btnIdUp + 5) as Button
+ button.performClick()
+ }.then { activity ->
+ // Click 5 up
+ val button = activity.findViewById(btnIdUp + 5) as Button
+ button.performClick()
+ }.then { activity ->
+ // Click 5 add
+ val button = activity.findViewById(btnIdAdd + 5) as Button
+ button.performClick()
+ }.then { activity ->
+ val textView = activity.findViewById(tvId + 5) as TextView
+ assertEquals("id: 5 amt: 2", textView.text)
+ }
+ }
+
+ @Test
+ fun testObserveKtxWithInline(): Unit = ensureSetup {
+ compose(
+ """
+ @Composable
+ fun SimpleComposable() {
+ val count = state { 1 }
+ Box {
+ repeat(count.value) {
+ Button(text="Increment", onClick={ count.value += 1 }, id=(41+it))
+ }
+ }
+ }
+
+ @Composable
+ fun Box(children: @Composable ()->Unit) {
+ LinearLayout(orientation=LinearLayout.VERTICAL) {
+ children()
+ }
+ }
+ """,
+ """
+ SimpleComposable()
+ """, noParameters
+ ).then { activity ->
+ val button = activity.findViewById(41) as Button
+ button.performClick()
+ button.performClick()
+ button.performClick()
+ button.performClick()
+ button.performClick()
+ }.then { activity ->
+ assertNotNull(activity.findViewById(46))
+ }
+ }
+
+ @Test
+ fun testKeyTag(): Unit = ensureSetup {
+ compose(
+ """
+ val list = mutableListOf(0,1,2,3)
+
+ @Composable
+ fun Reordering() {
+ LinearLayout {
+ Recompose { recompose ->
+ Button(
+ id=50,
+ text="Recompose!",
+ onClick={ list.add(list.removeAt(0)); recompose(); }
+ )
+ LinearLayout(id=100) {
+ for(id in list) {
+ key(id) {
+ StatefulButton()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Composable
+ // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
+ fun StatefulButton() {
+ val count = state { 0 }
+ Button(text="Clicked ${'$'}{count.value} times!", onClick={ count.value++ })
+ }
+ """,
+ """
+ Reordering()
+ """, noParameters
+ ).then { activity ->
+ val layout = activity.findViewById(100) as LinearLayout
+ layout.getChildAt(0).performClick()
+ }.then { activity ->
+ val recomposeButton = activity.findViewById(50) as Button
+ recomposeButton.performClick()
+ }.then { activity ->
+ val layout = activity.findViewById(100) as LinearLayout
+ assertEquals("Clicked 0 times!", (layout.getChildAt(0) as Button).text)
+ assertEquals("Clicked 0 times!", (layout.getChildAt(1) as Button).text)
+ assertEquals("Clicked 0 times!", (layout.getChildAt(2) as Button).text)
+ assertEquals("Clicked 1 times!", (layout.getChildAt(3) as Button).text)
+ }
+ }
+
+ @Test
+ fun testNonComposeParameters(): Unit = ensureSetup {
+ compose(
+ """
+ class Action(
+ val s: String = "",
+ val param: Int,
+ type: Set<Int> = setOf(),
+ val action: () -> Unit
+ )
+
+ @Composable
+ fun DefineAction(
+ onAction: Action = Action(param = 1) {},
+ children: @Composable ()->Unit
+ ) { }
+ """,
+ """"""
+ )
+ }
+
+ @Test
+ fun testStableParameters_Various(): Unit = ensureSetup {
+ val output = ArrayList<String>()
+ compose("""
+ val m = mutableStateOf(0)
+
+ @Immutable
+ data class ValueHolder(val value: Int)
+
+ var output = ArrayList<String>()
+
+ class NotStable { val value = 10 }
+
+ @Stable
+ class StableClass {
+ override fun equals(other: Any?) = true
+ }
+
+ enum class EnumState {
+ One,
+ Two
+ }
+
+ val mutableStateType = mutableStateOf(1)
+ val stateType: State<Int> = mutableStateType
+
+ @Composable
+ fun MemoInt(a: Int) {
+ output.add("MemoInt a=${'$'}a")
+ Button(id=101, text="memo ${'$'}a", onClick={ m.value++ })
+ }
+
+ @Composable
+ fun MemoFloat(a: Float) {
+ output.add("MemoFloat")
+ Button(text="memo ${'$'}a")
+ }
+
+ @Composable
+ fun MemoDouble(a: Double) {
+ output.add("MemoDouble")
+ Button(text="memo ${'$'}a")
+ }
+
+ @Composable
+ fun MemoNotStable(a: NotStable) {
+ output.add("MemoNotStable")
+ Button(text="memo ${'$'}{a.value}")
+ }
+
+ @Composable
+ fun MemoModel(a: ValueHolder) {
+ output.add("MemoModelHolder")
+ Button(text="memo ${'$'}{a.value}")
+ }
+
+ @Composable
+ fun MemoEnum(a: EnumState) {
+ output.add("MemoEnum")
+ Button(text="memo ${'$'}{a}")
+ }
+
+ @Composable
+ fun MemoStable(a: StableClass) {
+ output.add("MemoStable")
+ Button(text="memo stable")
+ }
+
+ @Composable
+ fun MemoMutableState(a: MutableState<Int>) {
+ output.add("MemoMutableState")
+ Button(text="memo ${'$'}{a.value}")
+ }
+
+ @Composable
+ fun MemoState(a: State<Int>) {
+ output.add("MemoState")
+ Button(text="memo ${'$'}{a.value}")
+ }
+
+ @Composable
+ fun TestSkipping(
+ a: Int,
+ b: Float,
+ c: Double,
+ d: NotStable,
+ e: ValueHolder,
+ f: EnumState,
+ g: StableClass,
+ h: MutableState<Int>,
+ i: State<Int>
+ ) {
+ val am = a + m.value
+ output.add("TestSkipping a=${'$'}a am=${'$'}am")
+ MemoInt(a=am)
+ MemoFloat(a=b)
+ MemoDouble(a=c)
+ MemoNotStable(a=d)
+ MemoModel(a=e)
+ MemoEnum(a=f)
+ MemoStable(a=g)
+ MemoMutableState(h)
+ MemoState(i)
+ }
+
+ @Composable
+ fun Main(v: ValueHolder, n: NotStable) {
+ TestSkipping(
+ a=1,
+ b=1f,
+ c=2.0,
+ d=NotStable(),
+ e=v,
+ f=EnumState.One,
+ g=StableClass(),
+ h=mutableStateType,
+ i=stateType
+ )
+ }
+ """, """
+ output = outerOutput
+ val v = ValueHolder(0)
+ Main(v, NotStable())
+ """, {
+ mapOf(
+ "outerOutput: ArrayList<String>" to output
+ )
+ }).then {
+ // Expect that all the methods are called in order
+ assertEquals(
+ "TestSkipping a=1 am=1, MemoInt a=1, MemoFloat, " +
+ "MemoDouble, MemoNotStable, MemoModelHolder, MemoEnum, MemoStable, " +
+ "MemoMutableState, MemoState",
+ output.joinToString()
+ )
+ output.clear()
+ }.then { activity ->
+ // Expect TestSkipping and MemoNotStable to be called because the test forces an extra compose.
+ assertEquals("TestSkipping a=1 am=1, MemoNotStable", output.joinToString())
+ output.clear()
+
+ // Change the model
+ val button = activity.findViewById(101) as Button
+ button.performClick()
+ }.then {
+ // Expect that only MemoInt (the parameter changed) and MemoNotStable (it has unstable parameters) were
+ // called then expect a second compose which should only MemoNotStable
+ assertEquals(
+ "TestSkipping a=1 am=2, MemoInt a=2, MemoNotStable, " +
+ "TestSkipping a=1 am=2, MemoNotStable",
+ output.joinToString()
+ )
+ }
+ }
+
+ @Test
+ fun testStableParameters_Lambdas(): Unit = ensureSetup {
+ val output = ArrayList<String>()
+ compose("""
+ val m = mutableStateOf(0)
+
+ var output = ArrayList<String>()
+ val unchanged: () -> Unit = { }
+
+ fun log(msg: String) { output.add(msg) }
+
+ @Composable
+ fun Container(children: @Composable () -> Unit) {
+ log("Container")
+ children()
+ }
+
+ @Composable
+ fun NormalLambda(index: Int, lambda: () -> Unit) {
+ log("NormalLambda(${'$'}index)")
+ Button(text="text")
+ }
+
+ @Composable
+ fun TestSkipping(unchanged: () -> Unit, changed: () -> Unit) {
+ log("TestSkipping")
+ Container {
+ NormalLambda(index = 1, lambda = unchanged)
+ NormalLambda(index = 2, lambda = unchanged)
+ NormalLambda(index = 3, lambda = unchanged)
+ NormalLambda(index = 4, lambda = changed)
+ }
+ }
+
+ fun forceNewLambda(): () -> Unit = { }
+
+ @Composable
+ fun Main(unchanged: () -> Unit) {
+ Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+ TestSkipping(unchanged = unchanged, changed = forceNewLambda())
+ }
+ """, """
+ output = outerOutput
+ Main(unchanged = unchanged)
+ """, {
+ mapOf(
+ "outerOutput: ArrayList<String>" to output
+ )
+ }).then {
+ // Expect that all the methods are called in order
+ assertEquals(
+ "TestSkipping, Container, NormalLambda(1), " +
+ "NormalLambda(2), NormalLambda(3), NormalLambda(4)",
+ output.joinToString()
+ )
+ output.clear()
+ }.then { activity ->
+ // Expect nothing to occur with no changes
+ assertEquals("", output.joinToString())
+ output.clear()
+
+ // Change the model
+ val button = activity.findViewById(101) as Button
+ button.performClick()
+ }.then {
+ // Expect only NormalLambda(4) to be called
+ assertEquals(
+ "TestSkipping, NormalLambda(4)",
+ output.joinToString()
+ )
+ }
+ }
+
+ @Test
+ fun testRecomposeScope(): Unit = ensureSetup {
+ compose("""
+ val m = mutableStateOf(0)
+
+ @Composable
+ inline fun InlineContainer(children: @Composable () -> Unit) {
+ children()
+ }
+
+ @Composable
+ fun Container(children: @Composable () -> Unit) {
+ children()
+ }
+
+ @Composable
+ fun Leaf(v: Int) {}
+
+ @Composable
+ fun Inline() {
+ InlineContainer {
+ Leaf(v = 1)
+ }
+ }
+
+ @Composable
+ fun Lambda() {
+ val a = 1
+ val b = 2
+ Container {
+ TextView(text = "value = ${'$'}{m.value}", id = 100)
+ Leaf(v = 1)
+ Leaf(v = a)
+ Leaf(v = b)
+ }
+ }
+ """,
+ """
+ Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+ Lambda()
+ """,
+ noParameters
+ ).then { activity ->
+ assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
+ val button = activity.findViewById<Button>(101)
+ button.performClick()
+ }.then { activity ->
+ assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
+ }
+ }
+
+ @Test
+ fun testRecomposeScope_ReceiverScope(): Unit = ensureSetup {
+ compose("""
+ val m = mutableStateOf(0)
+
+ class Receiver { var r: Int = 0 }
+
+ @Composable
+ fun Container(children: @Composable Receiver.() -> Unit) {
+ Receiver().children()
+ }
+
+ @Composable
+ fun Lambda() {
+ Container {
+ TextView(text = "value = ${'$'}{m.value}", id = 100)
+ }
+ }
+ """,
+ """
+ Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+ Lambda()
+ """,
+ noParameters
+ ).then { activity ->
+ assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
+ val button = activity.findViewById<Button>(101)
+ button.performClick()
+ }.then { activity ->
+ assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
+ }
+ }
+
+ @Test
+ fun testRecomposeScope_Method(): Unit = ensureSetup {
+ compose("""
+ val m = mutableStateOf(0)
+
+ @Composable
+ fun Leaf() { }
+
+ class SelfCompose {
+ var f1 = 0
+
+ @Composable
+ fun compose(f2: Int) {
+ TextView(
+ text = "f1=${'$'}f1, f2=${'$'}f2, m=${'$'}{m.value*f1*f2}",
+ id = 100
+ )
+ }
+ }
+
+ @Composable
+ fun InvokeSelfCompose() {
+ val r = remember() { SelfCompose() }
+ r.f1 = 1
+ r.compose(f2 = 10)
+ Leaf()
+ }
+ """,
+ """
+ Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
+ InvokeSelfCompose()
+ """,
+ noParameters
+ ).then { activity ->
+ assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=0")
+ val button = activity.findViewById<Button>(101)
+ button.performClick()
+ }.then { activity ->
+ assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=10")
+ }
}
}
+private val noParameters = { emptyMap<String, String>() }
+
private inline fun <reified T : PsiElement> PsiElement.parentOfType(): T? = parentOfType(T::class)
private fun <T : PsiElement> PsiElement.parentOfType(vararg classes: KClass<out T>): T? {
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolutionDiagnosticsTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolutionDiagnosticsTests.kt
deleted file mode 100644
index decde5b..0000000
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolutionDiagnosticsTests.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.plugins.kotlin
-
-class ComposeCallResolutionDiagnosticsTests : AbstractComposeDiagnosticsTest() {
-
- private var isSetup = false
- override fun setUp() {
- isSetup = true
- super.setUp()
- }
-
- private fun <T> ensureSetup(block: () -> T): T {
- if (!isSetup) setUp()
- return block()
- }
-
- private fun setupAndDoTest(text: String) = ensureSetup { doTest(text) }
-
- fun testImplicitlyPassedReceiverScope1() = setupAndDoTest(
- """
- import androidx.compose.*
- import android.widget.*
- import android.os.Bundle
- import android.app.Activity
- import android.widget.FrameLayout
-
- val x: Any? = null
-
- fun Activity.setViewContent(composable: @Composable () -> Unit): Composition? {
- assert(composable != x)
- return null
- }
-
- open class WebComponentActivity : Activity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setViewContent {
- FrameLayout {
- }
- }
- }
- }
- """
- )
-
- fun testSimpleReceiverScope() = setupAndDoTest(
- """
- import android.widget.FrameLayout
- import androidx.compose.Composable
- import androidx.ui.node.UiComposer
-
- class SomeScope {
- val composer: UiComposer get() = error("should not be called")
- }
-
- @Composable fun SomeScope.foo() {
- FrameLayout { }
- }
-
- """
- )
-}
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt
index 32e6f2c..c27b941 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposeCallResolverTests.kt
@@ -64,7 +64,6 @@
@Composable
fun test() {
<call>Foo()
- <emit>TextView(text="text")
<normal>Bar()
}
"""
@@ -198,12 +197,14 @@
import androidx.compose.*
import android.widget.LinearLayout
+ @Composable fun Group(content: @Composable () -> Unit) { content() }
+
@Composable
inline fun PointerInputWrapper(
crossinline children: @Composable () -> Unit
) {
// Hide the internals of PointerInputNode
- <emit>LinearLayout {
+ <call>Group {
<call>children()
}
}
@@ -231,15 +232,13 @@
"$calltype.")
when (calltype) {
- "<normal>" -> assert(!resolvedCall.isCall() && !resolvedCall.isEmit())
- "<emit>" -> assert(resolvedCall.isEmit())
+ "<normal>" -> assert(!resolvedCall.isCall())
"<call>" -> assert(resolvedCall.isCall())
else -> error("Call type of $calltype not recognized.")
}
}
}
- private fun ResolvedCall<*>.isEmit(): Boolean = candidateDescriptor is ComposableEmitDescriptor
private fun ResolvedCall<*>.isCall(): Boolean =
when (candidateDescriptor) {
is ComposableFunctionDescriptor -> true
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt
index b360a71..01f8b90 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamSignatureTests.kt
@@ -357,34 +357,6 @@
)
@Test
- fun testSimpleEmits(): Unit = checkApi(
- """
- import android.widget.LinearLayout
- import android.widget.TextView
-
- @Composable fun Example() {
- LinearLayout(id=123) {
- TextView(text="Hello World")
- }
- }
- """,
- """
- public final class TestKt {
- public final static Example(Landroidx/compose/Composer;II)V
- final static INNERCLASS TestKt%Example%4 null null
- }
- final class TestKt%Example%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function3 {
- <init>(I)V
- public final invoke(Landroidx/compose/Composer;II)V
- private final synthetic I %%changed
- public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
- final static INNERCLASS TestKt%Example%4 null null
- OUTERCLASS TestKt Example (Landroidx/compose/Composer;II)V
- }
- """
- )
-
- @Test
fun testCorrectComposerPassed2(): Unit = checkComposerParam(
"""
var a: Composer<*>? = null
@@ -475,21 +447,6 @@
)
@Test
- fun testCorrectComposerPassed6(): Unit = checkComposerParam(
- """
- import android.widget.TextView
-
- fun run() {
- invokeComposable(makeComposer()) {
- LinearLayout(id=123) {
- TextView(text="Hello World")
- }
- }
- }
- """
- )
-
- @Test
fun testDefaultParameters(): Unit = checkApi(
"""
@Composable fun Foo(x: Int = 0) {
@@ -935,33 +892,6 @@
}
@Test
- fun testCustomComposerCall(): Unit = validateBytecode(
- """
- class VectorScope(val composer: VectorComposer)
-
- @Composable fun VectorScope.Test(children: @Composable VectorScope.() -> Unit) {
- children()
- }
-
- internal class AnyApplyAdapter : ApplyAdapter<Any> {
- override fun Any.start(instance: Any) {}
- override fun Any.insertAt(index: Int, instance: Any) {}
- override fun Any.removeAt(index: Int, count: Int) {}
- override fun Any.move(from: Int, to: Int, count: Int) {}
- override fun Any.end(instance: Any, parent: Any) {}
- }
-
- class VectorComposer(
- val root: Any,
- slotTable: SlotTable,
- recomposer: Recomposer
- ) : Composer<Any>(slotTable, Applier(root, AnyApplyAdapter()), recomposer)
- """
- ) {
- it.contains("INVOKEVIRTUAL androidx/compose/Composer.startGroup")
- }
-
- @Test
fun testCallingProperties(): Unit = checkApi(
"""
@Composable val bar: Int get() { return 123 }
@@ -1213,43 +1143,6 @@
)
@Test
- fun testExtensionSetterEmit(): Unit = checkApi(
- """
- import android.widget.TextView
-
- private fun TextView.setRef(ref: (TextView) -> Unit) {}
-
- @Composable
- fun Test() {
- TextView(ref = { })
- }
- """,
- """
- public final class TestKt {
- private final static setRef(Landroid/widget/TextView;Lkotlin/jvm/functions/Function1;)V
- public final static Test(Landroidx/compose/Composer;II)V
- final static INNERCLASS TestKt%Test%1%1 null null
- final static INNERCLASS TestKt%Test%4 null null
- }
- final class TestKt%Test%1%1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function1 {
- <init>()V
- public final invoke(Landroid/widget/TextView;)V
- public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
- final static INNERCLASS TestKt%Test%1%1 null null
- OUTERCLASS TestKt Test (Landroidx/compose/Composer;II)V
- }
- final class TestKt%Test%4 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function3 {
- <init>(I)V
- public final invoke(Landroidx/compose/Composer;II)V
- private final synthetic I %%changed
- public synthetic bridge invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
- final static INNERCLASS TestKt%Test%4 null null
- OUTERCLASS TestKt Test (Landroidx/compose/Composer;II)V
- }
- """
- )
-
- @Test
fun testDexNaming(): Unit = checkApi(
"""
@Composable
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt
index 2e2062f..d21dfc1 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/ComposerParamTransformTests.kt
@@ -274,42 +274,6 @@
)
@Test
- fun testExtensionSetterEmit(): Unit = composerParam(
- """
- import android.widget.TextView
-
- private fun TextView.setRef(ref: (TextView) -> Unit) {}
-
- @ComposableContract(restartable = false)
- @Composable
- fun Test() {
- TextView(ref = { })
- }
- """,
- """
- private fun TextView.setRef(ref: Function1<TextView, Unit>) { }
- @ComposableContract(restartable = false)
- @Composable
- fun Test(%composer: Composer<*>?, %key: Int, %changed: Int) {
- %composer.startReplaceableGroup(%key)
- val tmp0 = remember({
- { it: TextView ->
- }
- }, %composer, <>, 0)
- %composer.emit(-1248659431, { context: @[ParameterName(name = 'context')] Context ->
- TextView(context)
- }
- ) {
- set(tmp0) { p0: Function1<TextView, Unit> ->
- setRef(p0)
- }
- }
- %composer.endReplaceableGroup()
- }
- """
- )
-
- @Test
fun testDexNaming(): Unit = composerParam(
"""
@Composable
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt
index 230cdc5..735a5ba 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/DefaultParamTransformTests.kt
@@ -172,18 +172,22 @@
%composer.startRestartGroup(%key)
val %dirty = %changed
val x = x
- if (%default and 0b0001 === 0 && %changed and 0b0110 === 0) {
- %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
+ if (%changed and 0b0110 === 0) {
+ %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
}
if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
%composer.startDefaults()
if (%default and 0b0001 !== 0) {
x = makeInt()
+ %dirty = %dirty and 0b0110.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0001 !== 0) {
+ %dirty = %dirty and 0b0110.inv()
+ }
}
} else {
%composer.skipToGroupEnd()
@@ -218,8 +222,8 @@
} else if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
}
- if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
- %dirty = %dirty or if (%composer.changed(b)) 0b00010000 else 0b1000
+ if (%changed and 0b00011000 === 0) {
+ %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(b)) 0b00010000 else 0b1000
}
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -229,10 +233,14 @@
}
if (%default and 0b0010 !== 0) {
b = a + 1
+ %dirty = %dirty and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
print(a)
print(b)
@@ -1207,6 +1215,7 @@
}
if (%default and 0b001000000000 !== 0) {
a09 = Foo()
+ %dirty = %dirty and 0b000110000000000000000000.inv()
}
if (%default and 0b010000000000 !== 0) {
a10 = 0
@@ -1273,10 +1282,17 @@
}
if (%default1 and 0b0001 !== 0) {
a31 = Foo()
+ %dirty2 = %dirty2 and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b001000000000 !== 0) {
+ %dirty = %dirty and 0b000110000000000000000000.inv()
+ }
+ if (%default1 and 0b0001 !== 0) {
+ %dirty2 = %dirty2 and 0b00011000.inv()
+ }
}
print("Hello world!")
} else {
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt
deleted file mode 100644
index cacd00e..0000000
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/EmitTransformTests.kt
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.plugins.kotlin
-
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.annotation.Config
-
-@RunWith(ComposeRobolectricTestRunner::class)
-@Config(
- manifest = Config.NONE,
- minSdk = 23,
- maxSdk = 23
-)
-class EmitTransformTests : AbstractIrTransformTest() {
- @Before
- fun before() {
- setUp()
- }
- private fun emitTransform(
- unchecked: String,
- checked: String,
- expectedTransformed: String,
- dumpTree: Boolean = false
- ) = verifyComposeIrTransform(
- """
- import androidx.compose.Composable
- import androidx.compose.ComposableContract
- import android.widget.TextView
- import android.widget.LinearLayout
-
- $checked
- """.trimIndent(),
- expectedTransformed,
- """
- import androidx.compose.Composable
- import androidx.compose.ComposableContract
- import android.widget.TextView
- import android.widget.LinearLayout
-
- $unchecked
- """.trimIndent(),
- dumpTree
- )
-
- @Test
- fun testSimpleEmit2(): Unit = emitTransform(
- """
- """,
- """
- import androidx.compose.state
- import androidx.compose.remember
- import android.widget.Button
-
- @Composable
- fun App() {
- val cond = state { true }
- val text = if (cond.value) remember { "abc" } else remember { "def" }
- Button(id=1, text=text, onClickListener={ cond.value = !cond.value })
- }
- """,
- """
- @Composable
- fun App(%composer: Composer<*>?, %key: Int, %changed: Int) {
- %composer.startRestartGroup(%key)
- if (%changed !== 0 || !%composer.skipping) {
- val cond = state(null, {
- val tmp0_return = true
- tmp0_return
- }, %composer, <>, 0, 0b0001)
- val text = if (cond.value) {
- %composer.startReplaceableGroup(<>)
- val tmp0_group = remember({
- val tmp0_return = "abc"
- tmp0_return
- }, %composer, <>, 0)
- %composer.endReplaceableGroup()
- tmp0_group
- } else {
- %composer.startReplaceableGroup(<>)
- val tmp1_group = remember({
- val tmp0_return = "def"
- tmp0_return
- }, %composer, <>, 0)
- %composer.endReplaceableGroup()
- tmp1_group
- }
- val tmp0 = text
- val tmp1 = remember(cond, {
- { it: View? ->
- cond.value = !cond.value
- }
- }, %composer, <>, 0)
- %composer.emit(1124847878, { context: @[ParameterName(name = 'context')] Context ->
- Button(context)
- }
- ) {
- set(1) { p0: Int ->
- setId(p0)
- }
- set(tmp0) { p0: CharSequence? ->
- setText(p0)
- }
- set(tmp1) { p0: Function1<View?, Unit>? ->
- setOnClickListener(p0)
- }
- }
- } else {
- %composer.skipToGroupEnd()
- }
- %composer.endRestartGroup()?.updateScope { %composer: Composer<*>?, %key: Int, %force: Int ->
- App(%composer, %key, %changed or 0b0001)
- }
- }
- """
- )
-}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
deleted file mode 100644
index f09ae93..0000000
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsCodegenTests.kt
+++ /dev/null
@@ -1,2476 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("MemberVisibilityCanBePrivate")
-
-package androidx.compose.plugins.kotlin
-
-import android.view.View
-import android.widget.Button
-import android.widget.LinearLayout
-import android.widget.TextView
-import androidx.compose.Composer
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.RuntimeEnvironment
-import org.robolectric.annotation.Config
-import java.net.URLClassLoader
-
-private val noParameters = { emptyMap<String, String>() }
-
-@RunWith(ComposeRobolectricTestRunner::class)
-@Config(
- manifest = Config.NONE,
- minSdk = 23,
- maxSdk = 23
-)
-class FcsCodegenTests : AbstractCodegenTest() {
-
- @Test
- fun testReturnValue(): Unit = ensureSetup {
- compose("""
- var a = 0
- var b = 0
-
- @Composable
- fun SimpleComposable() {
- a++
- val c = state { 0 }
- val d = remember(c.value) { b++; b }
- val recompose = invalidate
- Button(
- text=listOf(a, b, c.value, d).joinToString(", "),
- onClick={ c.value += 1 },
- id=42
- )
- Button(
- text="Recompose",
- onClick={ recompose() },
- id=43
- )
- }
- """,
- noParameters,
- "SimpleComposable()"
- ).then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals(
- button.text,
- listOf(
- 1, // SimpleComposable has run once
- 1, // memo has been called once because of initial mount
- 0, // state was in itialized at 0
- 1 // memo should return b
- ).joinToString(", ")
- )
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- val recompose = activity.findViewById(43) as Button
- assertEquals(
- button.text,
- listOf(
- 2, // SimpleComposable has run twice
- 2, // memo has been called twice, because state input has changed
- 1, // state was changed to 1
- 2 // memo should return b
- ).joinToString(", ")
- )
- recompose.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals(
- button.text,
- listOf(
- 3, // SimpleComposable has run three times
- 2, // memo was not called this time, because input didn't change
- 1, // state stayed at 1
- 2 // memo should return b
- ).joinToString(", ")
- )
- }
- }
-
- @Test
- fun testReorderedArgsReturnValue(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun SimpleComposable() {
- val x = remember(calculation = { "abc" }, v1 = "def")
- TextView(
- text=x,
- id=42
- )
- }
- """,
- noParameters,
- "SimpleComposable()"
- ).then { activity ->
- val button = activity.findViewById(42) as TextView
- assertEquals(button.text, "abc")
- }
- }
-
- @Test
- fun testTrivialReturnValue(): Unit = ensureSetup {
- compose("""
- @Composable
- fun <T> identity(value: T): T = value
-
- @Composable
- fun SimpleComposable() {
- val x = identity("def")
- TextView(
- text=x,
- id=42
- )
- }
- """,
- noParameters,
- "SimpleComposable()"
- ).then { activity ->
- val button = activity.findViewById(42) as TextView
- assertEquals(button.text, "def")
- }
- }
-
- @Test
- fun testForDevelopment(): Unit = ensureSetup {
- codegen(
- """
- import androidx.compose.*
-
- @Composable
- fun bar() {
-
- }
-
- @Composable
- fun foo() {
- TextView(text="Hello World")
- }
- """
- )
- }
-
- @Test
- fun testSimpleFunctionResolution(): Unit = ensureSetup {
- compose(
- """
- import androidx.compose.*
-
- @Composable
- fun noise(text: String) {}
-
- @Composable
- fun bar() {
- noise(text="Hello World")
- }
- """, noParameters,
- """
- """
- )
- }
-
- @Test
- fun testSimpleClassResolution(): Unit = ensureSetup {
- compose(
- """
- import android.widget.TextView
- import androidx.compose.*
-
- @Composable
- fun bar() {
- TextView(text="Hello World")
- }
- """, noParameters,
- """
- """
- )
- }
-
- @Test
- fun testSetContent(): Unit = ensureSetup {
- codegen(
- """
- fun fakeCompose(block: @Composable ()->Unit) { }
-
- class Test {
- fun test() {
- fakeCompose {
- LinearLayout(orientation = LinearLayout.VERTICAL) {}
- }
- }
- }
- """
- )
- }
-
- @Test
- fun testComposeWithResult(): Unit = ensureSetup {
- compose(
- """
- @Composable fun <T> identity(block: @Composable ()->T): T = block()
-
- @Composable
- fun TestCall() {
- val value: Any = identity { 12 }
- TextView(text = value.toString(), id = 100)
- }
- """,
- noParameters,
- "TestCall()"
- ).then { activity ->
- val textView = activity.findViewById<TextView>(100)
- assertEquals("12", textView.text)
- }
- }
-
- @Test
- fun testObservable(): Unit = ensureSetup {
- compose(
- """
- import android.widget.Button
- import androidx.compose.*
- import androidx.ui.androidview.adapters.setOnClick
-
- @Composable
- fun SimpleComposable() {
- FancyButton(state=mutableStateOf(0))
- }
-
- @Composable
- fun FancyButton(state: MutableState<Int>) {
- Button(text=("Clicked "+state.value+" times"), onClick={state.value++}, id=42)
- }
- """,
- noParameters,
- "SimpleComposable()"
- ).then { activity ->
- val button = activity.findViewById(42) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals("Clicked 3 times", button.text)
- }
- }
-
- @Test
- fun testObservableLambda(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun SimpleComposable(state: MutableState<Int>) {
- FancyBox2 {
- Button(
- text=("Button clicked "+state.value+" times"),
- onClick={state.value++},
- id=42
- )
- }
- }
-
- @Composable
- fun FancyBox2(children: @Composable ()->Unit) {
- children()
- }
- """,
- noParameters,
- "SimpleComposable(state=state { 0 })"
- ).then { activity ->
- val button = activity.findViewById(42) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals("Button clicked 3 times", button.text)
- }
- }
-
- @Test
- fun testObservableGenericFunction(): Unit = ensureSetup {
- compose("""
- @Composable
- fun <T> SimpleComposable(state: MutableState<Int>, value: T) {
- Button(
- text=("Button clicked "+state.value+" times: " + value),
- onClick={state.value++},
- id=42
- )
- }
- """,
- noParameters,
- "SimpleComposable(state=state { 0 }, value=\"Value\")"
- ).then { activity ->
- val button = activity.findViewById(42) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals("Button clicked 3 times: Value", button.text)
- }
- }
-
- @Test
- fun testObservableExtension(): Unit = ensureSetup {
- compose("""
-
- @Composable
- fun MutableState<Int>.Composable() {
- Button(
- text="Button clicked "+value+" times",
- onClick={value++},
- id=42
- )
- }
-
- val myCounter = mutableStateOf(0)
- """,
- noParameters,
- "myCounter.Composable()"
- ).then { activity ->
- val button = activity.findViewById<Button>(42)
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById<Button>(42)
- assertEquals("Button clicked 3 times", button.text)
- }
- }
-
- @Test
- fun testObserverableExpressionBody(): Unit = ensureSetup {
- compose("""
- @Composable
- fun SimpleComposable(counter: MutableState<Int>) =
- Button(
- text="Button clicked "+counter.value+" times",
- onClick={counter.value++},
- id=42
- )
-
- @Composable
- fun SimpleWrapper(counter: MutableState<Int>) = SimpleComposable(counter = counter)
-
- val myCounter = mutableStateOf(0)
- """,
- noParameters,
- "SimpleWrapper(counter = myCounter)"
- ).then { activity ->
- val button = activity.findViewById<Button>(42)
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById<Button>(42)
- assertEquals("Button clicked 3 times", button.text)
- }
- }
-
- @Test
- fun testObservableInlineWrapper(): Unit = ensureSetup {
- compose("""
- var inWrapper = false
- val counter = mutableStateOf(0)
-
- inline fun wrapper(block: () -> Unit) {
- inWrapper = true
- try {
- block()
- } finally {
- inWrapper = false
- }
- }
-
- @Composable
- fun SimpleComposable(state: MutableState<Int>) {
- wrapper {
- Button(
- text=("Button clicked "+state.value+" times"),
- onClick={state.value++},
- id=42
- )
- }
- }
- """,
- noParameters,
- "SimpleComposable(state=counter)"
- ).then { activity ->
- val button = activity.findViewById(42) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals("Button clicked 3 times", button.text)
- }
- }
-
- @Test
- fun testObservableDefaultParameter(): Unit = ensureSetup {
- compose("""
- val counter = mutableStateOf(0)
-
- @Composable
- fun SimpleComposable(state: MutableState<Int>, a: Int = 1, b: Int = 2) {
- Button(
- text=("State: ${'$'}{state.value} a = ${'$'}a b = ${'$'}b"),
- onClick={state.value++},
- id=42
- )
- }
- """,
- noParameters,
- "SimpleComposable(state=counter, b = 4)"
- ).then { activity ->
- val button = activity.findViewById(42) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById(42) as Button
- assertEquals("State: 3 a = 1 b = 4", button.text)
- }
- }
-
- @Test
- fun testObservableEarlyReturn(): Unit = ensureSetup {
- compose("""
-
- val counter = mutableStateOf(0)
-
- @Composable
- fun SimpleComposable(state: MutableState<Int>) {
- Button(
- text=("State: ${'$'}{state.value}"),
- onClick={state.value++},
- id=42
- )
-
- if (state.value > 2) return
-
- TextView(
- text="Included text",
- id=43
- )
- }
- """,
- noParameters,
- "SimpleComposable(state=counter)"
- ).then { activity ->
- // Check that the text view is in the view
- assertNotNull(activity.findViewById(43))
- val button = activity.findViewById(42) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- val button = activity.findViewById<Button>(42)
- assertEquals("State: 3", button.text)
-
- // Assert that the text view is no longer in the view
- assertNull(activity.findViewById<Button>(43))
- }
- }
-
- @Test
- fun testCGSimpleTextView(): Unit = ensureSetup {
- compose(
- """
- TextView(text="Hello, world!", id=42)
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testCGLocallyScopedFunction(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo() {
- @Composable fun Bar() {
- TextView(text="Hello, world!", id=42)
- }
- Bar()
- }
- """,
- noParameters,
- """
- Foo()
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testCGLocallyScopedExtensionFunction(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(x: String) {
- @Composable fun String.Bar() {
- TextView(text=this, id=42)
- }
- x.Bar()
- }
- """,
- noParameters,
- """
- Foo(x="Hello, world!")
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testImplicitReceiverScopeCall(): Unit = ensureSetup {
- compose(
- """
- import androidx.compose.*
-
- class Bar(val text: String)
-
- @Composable fun Bar.Foo() {
- TextView(text=text,id=42)
- }
-
- @Composable
- fun Bam(bar: Bar) {
- with(bar) {
- Foo()
- }
- }
- """,
- noParameters,
- """
- Bam(bar=Bar("Hello, world!"))
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testCGLocallyScopedInvokeOperator(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(x: String) {
- @Composable
- operator fun String.invoke() {
- TextView(text=this, id=42)
- }
- x()
- }
- """,
- noParameters,
- """
- Foo(x="Hello, world!")
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testTrivialExtensionFunction(): Unit = ensureSetup {
- compose(
- """ """,
- { mapOf<String, String>() },
- """
- val x = "Hello"
- @Composable fun String.foo() {}
- x.foo()
- """
- )
- }
-
- @Test
- fun testTrivialInvokeExtensionFunction(): Unit = ensureSetup {
- compose(
- """ """,
- noParameters,
- """
- val x = "Hello"
- @Composable operator fun String.invoke() {}
- x()
- """
- )
- }
-
- @Test
- fun testCGNSimpleTextView(): Unit = ensureSetup {
- compose(
- """
- TextView(text="Hello, world!", id=42)
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testInliningTemp(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(x: Double, children: @Composable Double.() -> Unit) {
- x.children()
- }
- """,
- { mapOf("foo" to "bar") },
- """
- Foo(x=1.0) {
- TextView(text=this.toString(), id=123)
- }
- """
- ).then { activity ->
- val textView = activity.findViewById(123) as TextView
- assertEquals("1.0", textView.text)
- }
- }
-
- @Test
- fun testInliningTemp2(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(onClick: Double.() -> Unit) {
-
- }
- """,
- { mapOf("foo" to "bar") },
- """
- Foo(onClick={})
- """
- ).then { }
- }
-
- @Test
- fun testInliningTemp3(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(onClick: (Double) -> Unit) {
-
- }
- """,
- { mapOf("foo" to "bar") },
- """
- Foo(onClick={})
- """
- ).then { }
- }
-
- @Test
- fun testInliningTemp4(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(onClick: (Double) -> Unit) {
-
- }
- """,
- { mapOf("foo" to "bar") },
- """
- Foo(onClick={})
- """
- ).then {}
- }
-
- @Test
- fun testInline_NonComposable_Identity(): Unit = ensureSetup {
- compose("""
- @Composable inline fun InlineWrapper(base: Int, children: @Composable ()->Unit) {
- children()
- }
- """,
- noParameters,
- """
- InlineWrapper(200) {
- TextView(text = "Test", id=101)
- }
- """).then { activity ->
- assertEquals("Test", activity.findViewById<TextView>(101).text)
- }
- }
-
- @Test
- fun testInline_Composable_Identity(): Unit = ensureSetup {
- compose("""
- @Composable
- inline fun InlineWrapper(base: Int, children: @Composable ()->Unit) {
- children()
- }
- """,
- noParameters,
- """
- InlineWrapper(200) {
- TextView(text = "Test", id=101)
- }
- """).then { activity ->
- assertEquals("Test", activity.findViewById<TextView>(101).text)
- }
- }
-
- @Test
- fun testInline_Composable_EmitChildren(): Unit = ensureSetup {
- compose("""
- @Composable
- inline fun InlineWrapper(base: Int, crossinline children: @Composable ()->Unit) {
- LinearLayout(id = base + 0) {
- children()
- }
- }
- """,
- noParameters,
- """
- InlineWrapper(200) {
- TextView(text = "Test", id=101)
- }
- """).then { activity ->
- val tv = activity.findViewById<TextView>(101)
- // Assert the TextView was created with the correct text
- assertEquals("Test", tv.text)
- // and it is the first child of the linear layout
- assertEquals(tv, activity.findViewById<LinearLayout>(200).getChildAt(0))
- }
- }
-
- @Test
- fun testCGNInlining(): Unit = ensureSetup {
- compose(
- """
- LinearLayout(orientation=LinearLayout.VERTICAL) {
- TextView(text="Hello, world!", id=42)
- }
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testCGUpdatedComposition(): Unit = ensureSetup {
- var value = "Hello, world!"
-
- compose(
- { mapOf("value" to value) }, """
- TextView(text=value, id=42)
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
-
- value = "Other value"
- }.then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Other value", textView.text)
- }
- }
-
- @Test
- fun testCGNUpdatedComposition(): Unit = ensureSetup {
- var value = "Hello, world!"
-
- compose(
- { mapOf("value" to value) }, """
- TextView(text=value, id=42)
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
-
- value = "Other value"
- }.then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Other value", textView.text)
- }
- }
-
- @Test
- fun testCGViewGroup(): Unit = ensureSetup {
- val tvId = 258
- val llId = 260
- var text = "Hello, world!"
- var orientation = LinearLayout.HORIZONTAL
-
- compose(
- { mapOf("text" to text, "orientation" to orientation) }, """
- LinearLayout(orientation=orientation, id=$llId) {
- TextView(text=text, id=$tvId)
- }
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val linearLayout = activity.findViewById(llId) as LinearLayout
-
- assertEquals(text, textView.text)
- assertEquals(orientation, linearLayout.orientation)
-
- text = "Other value"
- orientation = LinearLayout.VERTICAL
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val linearLayout = activity.findViewById(llId) as LinearLayout
-
- assertEquals(text, textView.text)
- assertEquals(orientation, linearLayout.orientation)
- }
- }
-
- // @Test
- fun testCGNAmbient(): Unit = ensureSetup {
- val tvId = 258
- var text = "Hello, world!"
-
- compose(
- """
-
- val StringAmbient = ambientOf<String> { "default" }
-
- @Composable fun Foo() {
- TextView(id=$tvId, text=StringAmbient.current)
- }
-
- """,
- { mapOf("text" to text) },
- """
- Providers(StringAmbient provides text) {
- Foo()
- }
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
- text = "wat"
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
- }
- }
-
- @Test
- fun testCGNFunctionComponent(): Unit = ensureSetup {
- var text = "Hello, world!"
- val tvId = 123
-
- compose(
- """
- @Composable
- fun Foo(text: String) {
- TextView(id=$tvId, text=text)
- }
-
- """,
- { mapOf("text" to text) },
- """
- Foo(text=text)
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
- text = "wat"
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
- }
- }
-
- // @Test
- fun testAmbientReference(): Unit = ensureSetup {
- val outerId = 123
- val innerId = 345
- val buttonId = 456
-
- compose(
- """
- fun buildPortal() = effectOf<Ambient.Reference> {
- context.buildReference()
- }
-
- fun <T> refFor() = memo { Ref<T>() }
-
- val textAmbient = Ambient.of { "default" }
-
- @Composable fun DisplayTest(id: Int) {
- val text = ambient(textAmbient)
- TextView(id=id, text=text)
- }
-
- @Composable fun PortalTest() {
- val portal = +buildPortal()
- val ref = +refFor<LinearLayout>()
- DisplayTest(id=$outerId)
-
- LinearLayout(ref=ref)
-
- val root = ref.value ?: error("Expected a linear")
-
- composeInto(root, portal) {
- DisplayTest(id=$innerId)
- }
- }
-
- @Composable
- fun TestApp() {
- val inc = state { 1 }
-
- Button(id=$buttonId, text="Click Me", onClick={ inc.value += 1 })
-
- textAmbient.Provider(value="value: ${"$"}{inc.value}") {
- PortalTest()
- }
- }
- """,
- { mapOf("text" to "") },
- """
- TestApp()
- """
- ).then { activity ->
- val inner = activity.findViewById(innerId) as TextView
- val outer = activity.findViewById(outerId) as TextView
- val button = activity.findViewById(buttonId) as Button
-
- assertEquals("inner", "value: 1", inner.text)
- assertEquals("outer", "value: 1", outer.text)
-
- button.performClick()
- }.then { activity ->
- val inner = activity.findViewById(innerId) as TextView
- val outer = activity.findViewById(outerId) as TextView
- val button = activity.findViewById(buttonId) as Button
-
- assertEquals("inner", "value: 2", inner.text)
- assertEquals("outer", "value: 2", outer.text)
-
- button.performClick()
- }.then { activity ->
- val inner = activity.findViewById(innerId) as TextView
- val outer = activity.findViewById(outerId) as TextView
-
- assertEquals("inner", "value: 3", inner.text)
- assertEquals("outer", "value: 3", outer.text)
- }
- }
-
- @Test
- fun testAmbientConsumedFromDefaultParameter(): Unit = ensureSetup {
- val initialText = "no text"
- val helloWorld = "Hello World!"
- compose("""
- val TextAmbient = ambientOf { "$initialText" }
-
- @Composable
- fun Main() {
- var text = state { "$initialText" }
- Providers(TextAmbient provides text.value) {
- LinearLayout {
- ConsumesAmbientFromDefaultParameter()
- Button(
- text = "Change ambient value",
- onClick={ text.value = "$helloWorld" },
- id=101
- )
- }
- }
- }
-
- @Composable
- fun ConsumesAmbientFromDefaultParameter(text: String = TextAmbient.current) {
- TextView(text = text, id = 42)
- }
- """,
- noParameters,
- "Main()"
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals(initialText, textView.text)
- }.then { activity ->
- val button = activity.findViewById(101) as Button
- button.performClick()
- }
- .then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals(helloWorld, textView.text)
- }
- }
-
- @Test
- fun testCGNViewGroup(): Unit = ensureSetup {
- val tvId = 258
- val llId = 260
- var text = "Hello, world!"
- var orientation = LinearLayout.HORIZONTAL
-
- compose(
- { mapOf("text" to text, "orientation" to orientation) }, """
- LinearLayout(orientation=orientation, id=$llId) {
- TextView(text=text, id=$tvId)
- }
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val linearLayout = activity.findViewById(llId) as LinearLayout
-
- assertEquals(text, textView.text)
- assertEquals(orientation, linearLayout.orientation)
-
- text = "Other value"
- orientation = LinearLayout.VERTICAL
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val linearLayout = activity.findViewById(llId) as LinearLayout
-
- assertEquals(text, textView.text)
- assertEquals(orientation, linearLayout.orientation)
- }
- }
-
- @Test
- fun testMemoization(): Unit = ensureSetup {
- val tvId = 258
- val tagId = (3 shl 24) or "composed_set".hashCode()
-
- compose(
- """
- var composedSet = mutableSetOf<String>()
- var inc = 1
-
- fun View.setComposed(composed: Set<String>) = setTag($tagId, composed)
-
- @Composable fun ComposePrimitive(value: Int) {
- composedSet.add("ComposePrimitive(" + value + ")")
- }
-
- class MutableThing(var value: String)
-
- val constantMutableThing = MutableThing("const")
-
- @Composable fun ComposeMutable(value: MutableThing) {
- composedSet.add("ComposeMutable(" + value.value + ")")
- }
- """,
- { mapOf("text" to "") },
- """
- composedSet.clear()
-
- ComposePrimitive(value=123)
- ComposePrimitive(value=inc)
- ComposeMutable(value=constantMutableThing)
- ComposeMutable(value=MutableThing("new"))
-
- TextView(id=$tvId, composed=composedSet)
-
- inc++
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val composedSet = textView.getComposedSet(tagId) ?: error(
- "expected a compose set to exist")
-
- fun assertContains(contains: Boolean, key: String) {
- assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
- }
-
- assertContains(true, "ComposePrimitive(123)")
- assertContains(true, "ComposePrimitive(1)")
- assertContains(true, "ComposeMutable(const)")
- assertContains(true, "ComposeMutable(new)")
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val composedSet = textView.getComposedSet(tagId)
- ?: error("expected a compose set to exist")
-
- fun assertContains(contains: Boolean, key: String) {
- assertEquals("composedSet contains key '$key'", contains, composedSet.contains(key))
- }
-
- // the primitive component skips based on equality
- assertContains(false, "ComposePrimitive(123)")
-
- // since the primitive changed, this one recomposes again
- assertContains(true, "ComposePrimitive(2)")
-
- // since this is a potentially mutable object, we don't skip based on it
- assertContains(true, "ComposeMutable(const)")
-
- // since its a new one every time, we definitely don't skip
- assertContains(true, "ComposeMutable(new)")
- }
- }
-
- @Test
- fun testInlineClassMemoization(): Unit = ensureSetup {
- val tvId = 258
- val tagId = (3 shl 24) or "composed_set".hashCode()
-
- compose(
- """
- inline class InlineInt(val value: Int)
- inline class InlineInlineInt(val value: InlineInt)
- inline class InlineMutableSet(val value: MutableSet<String>)
- fun View.setComposed(composed: Set<String>) = setTag($tagId, composed)
-
- val composedSet = mutableSetOf<String>()
- val constInlineInt = InlineInt(0)
- var inc = 2
- val constInlineMutableSet = InlineMutableSet(mutableSetOf("a"))
-
- @Composable fun ComposedInlineInt(value: InlineInt) {
- composedSet.add("ComposedInlineInt(" + value + ")")
- }
-
- @Composable fun ComposedInlineInlineInt(value: InlineInlineInt) {
- composedSet.add("ComposedInlineInlineInt(" + value + ")")
- }
-
- @Composable fun ComposedInlineMutableSet(value: InlineMutableSet) {
- composedSet.add("ComposedInlineMutableSet(" + value + ")")
- }
- """,
- { mapOf("text" to "") },
- """
- composedSet.clear()
-
- ComposedInlineInt(constInlineInt)
- ComposedInlineInt(InlineInt(1))
- ComposedInlineInt(InlineInt(inc))
- ComposedInlineInlineInt(InlineInlineInt(InlineInt(2)))
- ComposedInlineMutableSet(constInlineMutableSet)
-
- TextView(id=$tvId, composed=composedSet)
-
- inc++
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val composedSet = textView.getComposedSet(tagId)
- ?: error("expected a compose set to exist")
-
- // All composables should execute since it's the first time.
- assert(composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
- assert(composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
- assert(composedSet.contains("ComposedInlineInt(InlineInt(value=2))"))
- assert(composedSet.contains(
- "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
- assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val composedSet = textView.getComposedSet(tagId)
- ?: error("expected a compose set to exist")
-
- // InlineInt and InlineInlineInt are stable, so the corresponding composables should
- // not run for values equal to previous compositions.
- assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=0))"))
- assert(!composedSet.contains("ComposedInlineInt(InlineInt(value=1))"))
- assert(!composedSet.contains(
- "ComposedInlineInlineInt(InlineInlineInt(value=InlineInt(value=2)))"))
-
- // But if a stable composable is passed a new value, it should re-run.
- assert(composedSet.contains("ComposedInlineInt(InlineInt(value=3))"))
-
- // And composables for inline classes with non-stable underlying types should run.
- assert(composedSet.contains("ComposedInlineMutableSet(InlineMutableSet(value=[a]))"))
- }
- }
-
- @Test
- fun testStringParameterMemoization(): Unit = ensureSetup {
- val tvId = 258
- val tagId = (3 shl 24) or "composed_set".hashCode()
-
- compose(
- """
- fun View.setComposed(composed: Set<String>) = setTag($tagId, composed)
-
- val composedSet = mutableSetOf<String>()
- val FOO = "foo"
-
- @Composable fun ComposedString(value: String) {
- composedSet.add("ComposedString(" + value + ")")
- }
- """,
- { mapOf("text" to "") },
- """
- composedSet.clear()
-
- ComposedString(FOO)
- ComposedString("bar")
-
- TextView(id=$tvId, composed=composedSet)
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val composedSet = textView.getComposedSet(tagId)
- ?: error("expected a compose set to exist")
-
- // All composables should execute since it's the first time.
- assert(composedSet.contains("ComposedString(foo)"))
- assert(composedSet.contains("ComposedString(bar)"))
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- val composedSet = textView.getComposedSet(tagId)
- ?: error("expected a compose set to exist")
-
- assert(composedSet.isEmpty())
- }
- }
-
- @Test
- fun testCGNSimpleCall(): Unit = ensureSetup {
- val tvId = 258
- var text = "Hello, world!"
-
- compose(
- """
- @Composable fun SomeFun(x: String) {
- TextView(text=x, id=$tvId)
- }
- """,
- { mapOf("text" to text) },
- """
- SomeFun(x=text)
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
-
- text = "Other value"
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
- }
- }
-
- // @Test
- fun testCGNSimpleCall2(): Unit = ensureSetup {
- val tvId = 258
- var text = "Hello, world!"
- var someInt = 456
-
- compose(
- """
- class SomeClass(var x: String) {
- @Composable
- operator fun invoke(y: Int) {
- TextView(text="${"$"}x ${"$"}y", id=$tvId)
- }
- }
- """,
- { mapOf("text" to text, "someInt" to someInt) },
- """
- SomeClass(x=text, y=someInt)
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals("Hello, world! 456", textView.text)
-
- text = "Other value"
- someInt = 123
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals("Other value 123", textView.text)
- }
- }
-
- @Test
- fun testCGNCallWithChildren(): Unit = ensureSetup {
- val tvId = 258
- var text = "Hello, world!"
-
- compose(
- """
- @Composable
- fun Block(children: @Composable () -> Unit) {
- children()
- }
- """,
- { mapOf("text" to text) },
- """
- Block {
- Block {
- TextView(text=text, id=$tvId)
- }
- }
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
-
- text = "Other value"
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
-
- assertEquals(text, textView.text)
- }
- }
-
- // @Test
- fun testCGNStuff(): Unit = ensureSetup {
- val tvId = 258
- var num = 123
-
- compose(
- """
- class OneArg {
- var foo = 0
- @Composable
- operator fun invoke() {
- TextView(text="${"$"}foo", id=$tvId)
- }
- }
- fun OneArg.setBar(bar: Int) { foo = bar }
- """,
- { mapOf("num" to num) },
- """
- OneArg(bar=num)
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- assertEquals("$num", textView.text)
-
- num = 456
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- assertEquals("$num", textView.text)
- }
- }
-
- // @Test
- fun testTagBasedMemoization(): Unit = ensureSetup {
- val tvId = 258
- var text = "Hello World"
-
- compose(
- """
- class A {
- var foo = ""
- inner class B {
- @Composable
- operator fun invoke() {
- TextView(text=foo, id=$tvId)
- }
- }
- }
- """,
- { mapOf("text" to text) },
- """
- val a = A()
- a.foo = text
- a.B()
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- assertEquals(text, textView.text)
-
- text = "new value"
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- assertEquals(text, textView.text)
- }
- }
-
- @Test
- fun testCGComposableFunctionInvocationOneParameter(): Unit = ensureSetup {
- val tvId = 91
- var phone = "(123) 456-7890"
- compose(
- """
- @Composable
- fun Phone(value: String) {
- TextView(text=value, id=$tvId)
- }
- """, { mapOf("phone" to phone) }, """
- Phone(value=phone)
- """
- ).then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- assertEquals(phone, textView.text)
-
- phone = "(123) 456-7899"
- }.then { activity ->
- val textView = activity.findViewById(tvId) as TextView
- assertEquals(phone, textView.text)
- }
- }
-
- @Test
- fun testCGComposableFunctionInvocationTwoParameters(): Unit = ensureSetup {
- val tvId = 111
- val rsId = 112
- var left = 0
- var right = 0
- compose(
- """
- var addCalled = 0
-
- @Composable
- fun AddView(left: Int, right: Int) {
- addCalled++
- TextView(text="${'$'}left + ${'$'}right = ${'$'}{left + right}", id=$tvId)
- TextView(text="${'$'}addCalled", id=$rsId)
- }
- """, { mapOf("left" to left, "right" to right) }, """
- AddView(left=left, right=right)
- """
- ).then { activity ->
- // Should be called on the first compose
- assertEquals("1", (activity.findViewById(rsId) as TextView).text)
- assertEquals(
- "$left + $right = ${left + right}",
- (activity.findViewById(tvId) as TextView).text
- )
- }.then { activity ->
- // Should be skipped on the second compose
- assertEquals("1", (activity.findViewById(rsId) as TextView).text)
- assertEquals(
- "$left + $right = ${left + right}",
- (activity.findViewById(tvId) as TextView).text
- )
-
- left = 1
- }.then { activity ->
- // Should be called again because left changed.
- assertEquals("2", (activity.findViewById(rsId) as TextView).text)
- assertEquals(
- "$left + $right = ${left + right}",
- (activity.findViewById(tvId) as TextView).text
- )
-
- right = 41
- }.then { activity ->
- // Should be called again because right changed
- assertEquals("3", (activity.findViewById(rsId) as TextView).text)
- assertEquals(
- "$left + $right = ${left + right}",
- (activity.findViewById(tvId) as TextView).text
- )
- }.then { activity ->
- // Should be skipped because nothing changed
- assertEquals("3", (activity.findViewById(rsId) as TextView).text)
- }
- }
-
- @Test
- fun testImplicitReceiverPassing1(): Unit = ensureSetup {
- compose(
- """
- @Composable fun Int.Foo(x: @Composable Int.() -> Unit) {
- x()
- }
- """,
- { mapOf<String, String>() },
- """
- val id = 42
-
- id.Foo(x={
- TextView(text="Hello, world!", id=this)
- })
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testImplicitReceiverPassing2(): Unit = ensureSetup {
- compose(
- """
- @Composable fun Int.Foo(x: @Composable Int.(text: String) -> Unit, text: String) {
- x(text=text)
- }
-
- @Composable fun MyText(text: String, id: Int) {
- TextView(text=text, id=id)
- }
- """,
- { mapOf<String, String>() },
- """
- val id = 42
-
- id.Foo(text="Hello, world!", x={ text ->
- MyText(text=text, id=this)
- })
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testEffects1(): Unit = ensureSetup {
- compose(
- """
- import androidx.ui.androidview.adapters.*
-
- @Composable
- fun Counter() {
- var count = state { 0 }
- TextView(
- text=("Count: " + count.value),
- onClick={
- count.value += 1
- },
- id=42
- )
- }
- """,
- { mapOf<String, String>() },
- """
- Counter()
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Count: 0", textView.text)
- textView.performClick()
- }.then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Count: 1", textView.text)
- }
- }
-
- @Test
- fun testEffects2(): Unit = ensureSetup {
- compose(
- """
- import androidx.ui.androidview.adapters.*
-
- @Composable
- fun Counter() {
- var count = state { 0 }
- TextView(
- text=("Count: " + count.value),
- onClick={
- count.value += 1
- },
- id=42
- )
- }
- """,
- { mapOf<String, String>() },
- """
- Counter()
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Count: 0", textView.text)
- textView.performClick()
- }.then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Count: 1", textView.text)
- }
- }
-
- @Test
- fun testEffects3(): Unit = ensureSetup {
- val log = StringBuilder()
- compose(
- """
- import androidx.ui.androidview.adapters.*
-
- @Composable
- fun Counter(log: StringBuilder) {
- var count = state { 0 }
- onCommit {
- log.append("a")
- }
- onActive {
- log.append("b")
- }
- TextView(
- text=("Count: " + count.value),
- onClick={
- count.value += 1
- },
- id=42
- )
- }
- """,
- { mapOf("log" to log) },
- """
- Counter(log=log)
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Count: 0", textView.text)
- assertEquals("ab", log.toString())
-
- execute {
- textView.performClick()
- }
-
- assertEquals("Count: 1", textView.text)
- assertEquals("aba", log.toString())
- }
- }
-
- @Test
- fun testEffects4(): Unit = ensureSetup {
- val log = StringBuilder()
- compose(
- """
- import androidx.ui.androidview.adapters.*
-
- @Composable
- fun printer(log: StringBuilder, str: String) {
- onCommit {
- log.append(str)
- }
- }
-
- @Composable
- fun Counter(log: StringBuilder) {
- var count = state { 0 }
- printer(log, "" + count.value)
- TextView(
- text=("Count: " + count.value),
- onClick={
- count.value += 1
- },
- id=42
- )
- }
- """,
- { mapOf("log" to log) },
- """
- Counter(log=log)
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Count: 0", textView.text)
- assertEquals("0", log.toString())
-
- execute {
- textView.performClick()
- }
-
- assertEquals("Count: 1", textView.text)
- assertEquals("01", log.toString())
- }
- }
-
- @Test
- fun testVariableCalls1(): Unit = ensureSetup {
- compose(
- """
- val component = @Composable {
- TextView(text="Hello, world!", id=42)
- }
- """,
- { mapOf<String, String>() },
- """
- component()
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testVariableCalls2(): Unit = ensureSetup {
- compose(
- """
- val component = @Composable {
- TextView(text="Hello, world!", id=42)
- }
- class HolderA(val composable: @Composable () -> Unit)
-
- val holder = HolderA(component)
-
- """,
- { mapOf<String, String>() },
- """
- holder.composable()
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testVariableCalls3(): Unit = ensureSetup {
- compose(
- """
- val component = @Composable {
- TextView(text="Hello, world!", id=42)
- }
- class HolderB(val composable: @Composable () -> Unit) {
- @Composable
- fun Foo() {
- composable()
- }
- }
-
- val holder = HolderB(component)
-
- """,
- { mapOf<String, String>() },
- """
- holder.Foo()
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- // b/123721921
- @Test
- fun testDefaultParameters1(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(a: Int = 42, b: String) {
- TextView(text=b, id=a)
- }
- """,
- { mapOf<String, String>() },
- """
- Foo(b="Hello, world!")
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testDefaultParameters2(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun Foo(a: Int = 42, b: String, c: @Composable () -> Unit) {
- c()
- TextView(text=b, id=a)
- }
- """,
- { mapOf<String, String>() },
- """
- Foo(b="Hello, world!") {}
- """
- ).then { activity ->
- val textView = activity.findViewById(42) as TextView
- assertEquals("Hello, world!", textView.text)
- }
- }
-
- @Test
- fun testMovement(): Unit = ensureSetup {
- val tvId = 50
- val btnIdAdd = 100
- val btnIdUp = 200
- val btnIdDown = 300
-
- // Duplicate the steps to reproduce an issue discovered in the Reorder example
- compose(
- """
- fun <T> List<T>.move(from: Int, to: Int): List<T> {
- if (to < from) return move(to, from)
- val item = get(from)
- val currentItem = get(to)
- val left = if (from > 0) subList(0, from) else emptyList()
- val right = if (to < size) subList(to + 1, size) else emptyList()
- val middle = if (to - from > 1) subList(from + 1, to) else emptyList()
- return left + listOf(currentItem) + middle + listOf(item) + right
- }
-
- @Composable
- fun Reordering() {
- val items = state { listOf(1, 2, 3, 4, 5) }
-
- LinearLayout(orientation=LinearLayout.VERTICAL) {
- items.value.forEachIndexed { index, id ->
- key(id) {
- Item(
- id=id,
- onMove={ amount ->
- val next = index + amount
- if (next >= 0 && next < items.value.size) {
- items.value = items.value.move(index, index + amount)
- }
- }
- )
- }
- }
- }
- }
-
- @Composable
- // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
- fun Item(id: Int, onMove: (Int) -> Unit) {
- val count = state { 0 }
- LinearLayout(orientation=LinearLayout.HORIZONTAL) {
- TextView(id=(id+$tvId), text="id: ${'$'}id amt: ${'$'}{count.value}")
- Button(id=(id+$btnIdAdd), text="+", onClick={ count.value++ })
- Button(id=(id+$btnIdUp), text="Up", onClick={ onMove(1) })
- Button(id=(id+$btnIdDown), text="Down", onClick={ onMove(-1) })
- }
- }
- """, noParameters,
- """
- Reordering()
- """
- ).then { activity ->
- // Click 5 add
- val button = activity.findViewById(btnIdAdd + 5) as Button
- button.performClick()
- }.then { activity ->
- // Click 5 down
- val button = activity.findViewById(btnIdDown + 5) as Button
- button.performClick()
- }.then { activity ->
- // Click 5 down
- val button = activity.findViewById(btnIdDown + 5) as Button
- button.performClick()
- }.then { activity ->
- // Click 5 up
- val button = activity.findViewById(btnIdUp + 5) as Button
- button.performClick()
- }.then { activity ->
- // Click 5 up
- val button = activity.findViewById(btnIdUp + 5) as Button
- button.performClick()
- }.then { activity ->
- // Click 5 add
- val button = activity.findViewById(btnIdAdd + 5) as Button
- button.performClick()
- }.then { activity ->
- val textView = activity.findViewById(tvId + 5) as TextView
- assertEquals("id: 5 amt: 2", textView.text)
- }
- }
-
- @Test
- fun testObserveKtxWithInline(): Unit = ensureSetup {
- compose(
- """
- @Composable
- fun SimpleComposable() {
- val count = state { 1 }
- Box {
- repeat(count.value) {
- Button(text="Increment", onClick={ count.value += 1 }, id=(41+it))
- }
- }
- }
-
- @Composable
- fun Box(children: @Composable ()->Unit) {
- LinearLayout(orientation=LinearLayout.VERTICAL) {
- children()
- }
- }
- """, noParameters,
- """
- SimpleComposable()
- """
- ).then { activity ->
- val button = activity.findViewById(41) as Button
- button.performClick()
- button.performClick()
- button.performClick()
- button.performClick()
- button.performClick()
- }.then { activity ->
- assertNotNull(activity.findViewById(46))
- }
- }
-
- @Test
- fun testKeyTag(): Unit = ensureSetup {
- compose(
- """
- val list = mutableListOf(0,1,2,3)
-
- @Composable
- fun Reordering() {
- LinearLayout {
- Recompose { recompose ->
- Button(
- id=50,
- text="Recompose!",
- onClick={ list.add(list.removeAt(0)); recompose(); }
- )
- LinearLayout(id=100) {
- for(id in list) {
- key(id) {
- StatefulButton()
- }
- }
- }
- }
- }
- }
-
- @Composable
- // TODO: Investigate making this private; looks like perhaps a compiler bug as of rebase
- fun StatefulButton() {
- val count = state { 0 }
- Button(text="Clicked ${'$'}{count.value} times!", onClick={ count.value++ })
- }
- """, noParameters,
- """
- Reordering()
- """
- ).then { activity ->
- val layout = activity.findViewById(100) as LinearLayout
- layout.getChildAt(0).performClick()
- }.then { activity ->
- val recomposeButton = activity.findViewById(50) as Button
- recomposeButton.performClick()
- }.then { activity ->
- val layout = activity.findViewById(100) as LinearLayout
- assertEquals("Clicked 0 times!", (layout.getChildAt(0) as Button).text)
- assertEquals("Clicked 0 times!", (layout.getChildAt(1) as Button).text)
- assertEquals("Clicked 0 times!", (layout.getChildAt(2) as Button).text)
- assertEquals("Clicked 1 times!", (layout.getChildAt(3) as Button).text)
- }
- }
-
- @Test
- fun testNonFcs(): Unit = ensureSetup {
- compose(
- """
-
- class MyTextView(context: Context) : TextView(context) {}
-
- fun foo(context: Context): TextView = MyTextView(context=context)
-
- """, noParameters,
- """
- """
- )
- }
-
- @Test
- fun testNonComposeParameters(): Unit = ensureSetup {
- compose(
- """
- class Action(
- val s: String = "",
- val param: Int,
- type: Set<Int> = setOf(),
- val action: () -> Unit
- )
-
- @Composable
- fun DefineAction(
- onAction: Action = Action(param = 1) {},
- children: @Composable ()->Unit
- ) { }
- """
- )
- }
-
- @Test
- fun testStableParameters_Various(): Unit = ensureSetup {
- val output = ArrayList<String>()
- compose("""
- val m = mutableStateOf(0)
-
- @Immutable
- data class ValueHolder(val value: Int)
-
- var output = ArrayList<String>()
-
- class NotStable { val value = 10 }
-
- @Stable
- class StableClass {
- override fun equals(other: Any?) = true
- }
-
- enum class EnumState {
- One,
- Two
- }
-
- val mutableStateType = mutableStateOf(1)
- val stateType: State<Int> = mutableStateType
-
- @Composable
- fun MemoInt(a: Int) {
- output.add("MemoInt a=${'$'}a")
- Button(id=101, text="memo ${'$'}a", onClick={ m.value++ })
- }
-
- @Composable
- fun MemoFloat(a: Float) {
- output.add("MemoFloat")
- Button(text="memo ${'$'}a")
- }
-
- @Composable
- fun MemoDouble(a: Double) {
- output.add("MemoDouble")
- Button(text="memo ${'$'}a")
- }
-
- @Composable
- fun MemoNotStable(a: NotStable) {
- output.add("MemoNotStable")
- Button(text="memo ${'$'}{a.value}")
- }
-
- @Composable
- fun MemoModel(a: ValueHolder) {
- output.add("MemoModelHolder")
- Button(text="memo ${'$'}{a.value}")
- }
-
- @Composable
- fun MemoEnum(a: EnumState) {
- output.add("MemoEnum")
- Button(text="memo ${'$'}{a}")
- }
-
- @Composable
- fun MemoStable(a: StableClass) {
- output.add("MemoStable")
- Button(text="memo stable")
- }
-
- @Composable
- fun MemoMutableState(a: MutableState<Int>) {
- output.add("MemoMutableState")
- Button(text="memo ${'$'}{a.value}")
- }
-
- @Composable
- fun MemoState(a: State<Int>) {
- output.add("MemoState")
- Button(text="memo ${'$'}{a.value}")
- }
-
- @Composable
- fun TestSkipping(
- a: Int,
- b: Float,
- c: Double,
- d: NotStable,
- e: ValueHolder,
- f: EnumState,
- g: StableClass,
- h: MutableState<Int>,
- i: State<Int>
- ) {
- val am = a + m.value
- output.add("TestSkipping a=${'$'}a am=${'$'}am")
- MemoInt(a=am)
- MemoFloat(a=b)
- MemoDouble(a=c)
- MemoNotStable(a=d)
- MemoModel(a=e)
- MemoEnum(a=f)
- MemoStable(a=g)
- MemoMutableState(h)
- MemoState(i)
- }
-
- @Composable
- fun Main(v: ValueHolder, n: NotStable) {
- TestSkipping(
- a=1,
- b=1f,
- c=2.0,
- d=NotStable(),
- e=v,
- f=EnumState.One,
- g=StableClass(),
- h=mutableStateType,
- i=stateType
- )
- }
- """, {
- mapOf(
- "outerOutput: ArrayList<String>" to output
- )
- }, """
- output = outerOutput
- val v = ValueHolder(0)
- Main(v, NotStable())
- """).then {
- // Expect that all the methods are called in order
- assertEquals(
- "TestSkipping a=1 am=1, MemoInt a=1, MemoFloat, " +
- "MemoDouble, MemoNotStable, MemoModelHolder, MemoEnum, MemoStable, " +
- "MemoMutableState, MemoState",
- output.joinToString()
- )
- output.clear()
- }.then { activity ->
- // Expect TestSkipping and MemoNotStable to be called because the test forces an extra compose.
- assertEquals("TestSkipping a=1 am=1, MemoNotStable", output.joinToString())
- output.clear()
-
- // Change the model
- val button = activity.findViewById(101) as Button
- button.performClick()
- }.then {
- // Expect that only MemoInt (the parameter changed) and MemoNotStable (it has unstable parameters) were
- // called then expect a second compose which should only MemoNotStable
- assertEquals(
- "TestSkipping a=1 am=2, MemoInt a=2, MemoNotStable, " +
- "TestSkipping a=1 am=2, MemoNotStable",
- output.joinToString()
- )
- }
- }
-
- @Test
- fun testStableParameters_Lambdas(): Unit = ensureSetup {
- val output = ArrayList<String>()
- compose("""
- val m = mutableStateOf(0)
-
- var output = ArrayList<String>()
- val unchanged: () -> Unit = { }
-
- fun log(msg: String) { output.add(msg) }
-
- @Composable
- fun Container(children: @Composable () -> Unit) {
- log("Container")
- children()
- }
-
- @Composable
- fun NormalLambda(index: Int, lambda: () -> Unit) {
- log("NormalLambda(${'$'}index)")
- Button(text="text")
- }
-
- @Composable
- fun TestSkipping(unchanged: () -> Unit, changed: () -> Unit) {
- log("TestSkipping")
- Container {
- NormalLambda(index = 1, lambda = unchanged)
- NormalLambda(index = 2, lambda = unchanged)
- NormalLambda(index = 3, lambda = unchanged)
- NormalLambda(index = 4, lambda = changed)
- }
- }
-
- fun forceNewLambda(): () -> Unit = { }
-
- @Composable
- fun Main(unchanged: () -> Unit) {
- Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
- TestSkipping(unchanged = unchanged, changed = forceNewLambda())
- }
- """, {
- mapOf(
- "outerOutput: ArrayList<String>" to output
- )
- }, """
- output = outerOutput
- Main(unchanged = unchanged)
- """).then {
- // Expect that all the methods are called in order
- assertEquals(
- "TestSkipping, Container, NormalLambda(1), " +
- "NormalLambda(2), NormalLambda(3), NormalLambda(4)",
- output.joinToString()
- )
- output.clear()
- }.then { activity ->
- // Expect nothing to occur with no changes
- assertEquals("", output.joinToString())
- output.clear()
-
- // Change the model
- val button = activity.findViewById(101) as Button
- button.performClick()
- }.then {
- // Expect only NormalLambda(4) to be called
- assertEquals(
- "TestSkipping, NormalLambda(4)",
- output.joinToString()
- )
- }
- }
-
- @Test
- fun testRecomposeScope(): Unit = ensureSetup {
- compose("""
- val m = mutableStateOf(0)
-
- @Composable
- inline fun InlineContainer(children: @Composable () -> Unit) {
- children()
- }
-
- @Composable
- fun Container(children: @Composable () -> Unit) {
- children()
- }
-
- @Composable
- fun Leaf(v: Int) {}
-
- @Composable
- fun Inline() {
- InlineContainer {
- Leaf(v = 1)
- }
- }
-
- @Composable
- fun Lambda() {
- val a = 1
- val b = 2
- Container {
- TextView(text = "value = ${'$'}{m.value}", id = 100)
- Leaf(v = 1)
- Leaf(v = a)
- Leaf(v = b)
- }
- }
- """,
- noParameters,
- """
- Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
- Lambda()
- """
- ).then { activity ->
- assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
- val button = activity.findViewById<Button>(101)
- button.performClick()
- }.then { activity ->
- assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
- }
- }
-
- @Test
- fun testRecomposeScope_ReceiverScope(): Unit = ensureSetup {
- compose("""
- val m = mutableStateOf(0)
-
- class Receiver { var r: Int = 0 }
-
- @Composable
- fun Container(children: @Composable Receiver.() -> Unit) {
- Receiver().children()
- }
-
- @Composable
- fun Lambda() {
- Container {
- TextView(text = "value = ${'$'}{m.value}", id = 100)
- }
- }
- """,
- noParameters,
- """
- Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
- Lambda()
- """
- ).then { activity ->
- assertEquals(activity.findViewById<TextView>(100).text, "value = 0")
- val button = activity.findViewById<Button>(101)
- button.performClick()
- }.then { activity ->
- assertEquals(activity.findViewById<TextView>(100).text, "value = 1")
- }
- }
-
- @Test
- fun testRecomposeScope_Method(): Unit = ensureSetup {
- compose("""
- val m = mutableStateOf(0)
-
- @Composable
- fun Leaf() { }
-
- class SelfCompose {
- var f1 = 0
-
- @Composable
- fun compose(f2: Int) {
- TextView(
- text = "f1=${'$'}f1, f2=${'$'}f2, m=${'$'}{m.value*f1*f2}",
- id = 100
- )
- }
- }
-
- @Composable
- fun InvokeSelfCompose() {
- val r = remember() { SelfCompose() }
- r.f1 = 1
- r.compose(f2 = 10)
- Leaf()
- }
- """,
- noParameters,
- """
- Button(id=101, text="model ${'$'}{m.value}", onClick={ m.value++ })
- InvokeSelfCompose()
- """
- ).then { activity ->
- assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=0")
- val button = activity.findViewById<Button>(101)
- button.performClick()
- }.then { activity ->
- assertEquals(activity.findViewById<TextView>(100).text, "f1=1, f2=10, m=10")
- }
- }
-
- fun codegen(text: String, dumpClasses: Boolean = false) {
- val className = "Test_${uniqueNumber++}"
- val fileName = "$className.kt"
-
- classLoader(
- """
- import android.content.Context
- import android.widget.*
- import androidx.compose.*
-
- $text
-
- """, fileName, dumpClasses
- )
- }
-
- fun compose(text: String, dumpClasses: Boolean = false): RobolectricComposeTester = compose(
- { mapOf<String, Any>() },
- text,
- dumpClasses
- )
-
- fun <T : Any> compose(
- valuesFactory: () -> Map<String, T>,
- text: String,
- dumpClasses: Boolean = false
- ) = compose("", valuesFactory, text, dumpClasses)
-
- private fun execute(block: () -> Unit) {
- val scheduler = RuntimeEnvironment.getMasterScheduler()
- scheduler.pause()
- block()
- scheduler.advanceToLastPostedRunnable()
- }
-
- fun <T : Any> compose(
- prefix: String,
- valuesFactory: () -> Map<String, T>,
- text: String,
- dumpClasses: Boolean = false
- ): RobolectricComposeTester {
- val className = "Test_${uniqueNumber++}"
- val fileName = "$className.kt"
-
- val candidateValues = valuesFactory()
-
- @Suppress("NO_REFLECTION_IN_CLASS_PATH")
- val parameterList = candidateValues.map {
- if (it.key.contains(':')) {
- it.key
- } else "${it.key}: ${it.value::class.qualifiedName}"
- }.joinToString()
- val parameterTypes = candidateValues.map {
- it.value::class.javaPrimitiveType ?: it.value::class.javaObjectType
- }.toTypedArray()
-
- val compiledClasses = classLoader(
- """
- import android.content.Context
- import android.widget.*
- import android.view.View
- import androidx.compose.*
- import androidx.ui.androidview.adapters.*
-
- $prefix
-
- class $className {
-
- @Composable
- fun test($parameterList) {
- $text
- }
- }
- """, fileName, dumpClasses
- )
-
- val allClassFiles = compiledClasses.allGeneratedFiles.filter {
- it.relativePath.endsWith(".class")
- }
-
- val loader = URLClassLoader(emptyArray(), this.javaClass.classLoader)
-
- val instanceClass = run {
- var instanceClass: Class<*>? = null
- var loadedOne = false
- for (outFile in allClassFiles) {
- val bytes = outFile.asByteArray()
- val loadedClass = loadClass(loader, null, bytes)
- if (loadedClass.name == className) instanceClass = loadedClass
- loadedOne = true
- }
- if (!loadedOne) error("No classes loaded")
- instanceClass ?: error("Could not find class $className in loaded classes")
- }
-
- val instanceOfClass = instanceClass.newInstance()
- val testMethod = instanceClass.getMethod(
- "test",
- *parameterTypes,
- Composer::class.java,
- Int::class.java,
- Int::class.java
- )
-
- return compose { composer, _, _ ->
- val values = valuesFactory()
- val arguments = values.map { it.value as Any }.toTypedArray()
- testMethod.invoke(instanceOfClass, *arguments, composer, 0, 1)
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- fun View.getComposedSet(tagId: Int): Set<String>? = getTag(tagId) as? Set<String>
-}
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt
index adbfcef..6d32c5c 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FcsTypeResolutionTests.kt
@@ -79,7 +79,8 @@
fun testResolutionInsideWhenExpression() = doTest(
"""
import androidx.compose.*
- import android.widget.TextView
+
+ @Composable fun TextView(text: String) { print(text) }
@Composable fun doSomething(foo: Boolean) {
when (foo) {
@@ -107,7 +108,7 @@
children2: @Composable () -> Unit,
value2: Int
) {
- LinearLayout {
+ Foo(123) {
// named argument
Foo(x=value)
@@ -498,13 +499,6 @@
<!CANNOT_INFER_PARAMETER_TYPE!>y<!>, <!CANNOT_INFER_PARAMETER_TYPE!>z<!> ->
println(x + y + z)
}
-
- Button()
- LinearLayout()
-
- LinearLayout {}
-
- Button <!TOO_MANY_ARGUMENTS!>{}<!>
}
""".trimIndent()
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt
index 09f4e29..fc9f202 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/FunctionBodySkippingTransformTests.kt
@@ -84,7 +84,7 @@
if (%default and 0b0010 !== 0) {
y = 0
}
- Wrap(restartableFunction(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ Wrap(composableLambda(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
if (x > 0) {
%composer.startReplaceableGroup(<>)
@@ -118,13 +118,9 @@
}
""",
"""
- import androidx.compose.Untracked
- import androidx.compose.ExperimentalComposeApi
-
@Composable
fun Test(x: Int = 0, y: Int = 0) {
- @OptIn(ExperimentalComposeApi::class)
- Wrap @Untracked {
+ Wrap @ComposableContract(tracked = false) {
A(x)
}
}
@@ -153,7 +149,7 @@
if (%default and 0b0010 !== 0) {
y = 0
}
- Wrap(restartableFunction(%composer, <>, false) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ Wrap(composableLambda(%composer, <>, false) { %composer: Composer<*>?, %key: Int, %changed: Int ->
%composer.startReplaceableGroup(%key)
A(x, 0, %composer, <>, 0b0110 and %dirty, 0b0010)
%composer.endReplaceableGroup()
@@ -264,8 +260,8 @@
} else if (%changed and 0b01100000 === 0) {
%dirty = %dirty or if (%composer.changed(arrangement)) 0b01000000 else 0b00100000
}
- if (%default and 0b1000 === 0 && %changed and 0b000110000000 === 0) {
- %dirty = %dirty or if (%composer.changed(crossAxisAlignment)) 0b000100000000 else 0b10000000
+ if (%changed and 0b000110000000 === 0) {
+ %dirty = %dirty or if (%default and 0b1000 === 0 && %composer.changed(crossAxisAlignment)) 0b000100000000 else 0b10000000
}
if (%default and 0b00010000 !== 0) {
%dirty = %dirty or 0b011000000000
@@ -288,6 +284,7 @@
}
if (%default and 0b1000 !== 0) {
crossAxisAlignment = Companion.Start
+ %dirty = %dirty and 0b000110000000.inv()
}
if (%default and 0b00010000 !== 0) {
crossAxisSize = SizeMode.Wrap
@@ -295,6 +292,9 @@
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b1000 !== 0) {
+ %dirty = %dirty and 0b000110000000.inv()
+ }
}
println()
} else {
@@ -321,8 +321,8 @@
} else if (%changed and 0b00011000 === 0) {
%dirty = %dirty or if (%composer.changed(verticalArrangement)) 0b00010000 else 0b1000
}
- if (%default and 0b0100 === 0 && %changed and 0b01100000 === 0) {
- %dirty = %dirty or if (%composer.changed(horizontalGravity)) 0b01000000 else 0b00100000
+ if (%changed and 0b01100000 === 0) {
+ %dirty = %dirty or if (%default and 0b0100 === 0 && %composer.changed(horizontalGravity)) 0b01000000 else 0b00100000
}
if (%default and 0b1000 !== 0) {
%dirty = %dirty or 0b000110000000
@@ -340,10 +340,14 @@
}
if (%default and 0b0100 !== 0) {
horizontalGravity = Companion.Start
+ %dirty = %dirty and 0b01100000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0100 !== 0) {
+ %dirty = %dirty and 0b01100000.inv()
+ }
}
val tmp0_orientation = LayoutOrientation.Vertical
val tmp1_arrangement = verticalArrangement
@@ -421,18 +425,22 @@
%composer.startRestartGroup(%key)
val %dirty = %changed
val a = a
- if (%default and 0b0001 === 0 && %changed and 0b0110 === 0) {
- %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
+ if (%changed and 0b0110 === 0) {
+ %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(a)) 0b0100 else 0b0010
}
if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
%composer.startDefaults()
if (%default and 0b0001 !== 0) {
a = newInt()
+ %dirty = %dirty and 0b0110.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0001 !== 0) {
+ %dirty = %dirty and 0b0110.inv()
+ }
}
print(a)
} else {
@@ -489,10 +497,14 @@
}
if (%default and 0b0010 !== 0) {
shape = RectangleShape
+ %dirty = %dirty and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
println()
} else {
@@ -533,8 +545,8 @@
} else if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(modifier)) 0b0100 else 0b0010
}
- if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
- %dirty = %dirty or if (%composer.changed(children)) 0b00010000 else 0b1000
+ if (%changed and 0b00011000 === 0) {
+ %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(children)) 0b00010000 else 0b1000
}
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -543,17 +555,21 @@
modifier = Companion
}
if (%default and 0b0010 !== 0) {
- children = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ children = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
Unit
} else {
%composer.skipToGroupEnd()
}
}
+ %dirty = %dirty and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
println()
} else {
@@ -582,7 +598,7 @@
}
""",
"""
- val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -614,7 +630,7 @@
}
""",
"""
- val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val foo: Function5<Int, Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { x: Int, y: Foo, %composer: Composer<*>?, %key: Int, %changed: Int ->
A(x, %composer, <>, 0b0110 and %changed)
B(y, %composer, <>, 0b0110 and %changed shr 0b0010)
}
@@ -655,7 +671,7 @@
fun Example(%composer: Composer<*>?, %key: Int, %changed: Int) {
%composer.startRestartGroup(%key)
if (%changed !== 0 || !%composer.skipping) {
- SomeThing(restartableFunction(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ SomeThing(composableLambda(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
val id = object
} else {
@@ -843,8 +859,8 @@
} else if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
}
- if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
- %dirty = %dirty or if (%composer.changed(b)) 0b00010000 else 0b1000
+ if (%changed and 0b00011000 === 0) {
+ %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(b)) 0b00010000 else 0b1000
}
if (%default and 0b0100 !== 0) {
%dirty = %dirty or 0b01100000
@@ -859,6 +875,7 @@
}
if (%default and 0b0010 !== 0) {
b = makeInt(%composer, <>, 0)
+ %dirty = %dirty and 0b00011000.inv()
}
if (%default and 0b0100 !== 0) {
c = 0
@@ -866,6 +883,9 @@
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
} else {
%composer.skipToGroupEnd()
@@ -936,7 +956,7 @@
if (%default and 0b0010 !== 0) {
y = 0
}
- Wrap(10, restartableFunction(%composer, <>, true) { it: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+ Wrap(10, composableLambda(%composer, <>, true) { it: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(it)) 0b0100 else 0b0010
@@ -994,7 +1014,7 @@
}
""",
"""
- val test: Function4<Int, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { x: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val test: Function4<Int, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { x: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -1102,10 +1122,14 @@
}
if (%default and 0b0010 !== 0) {
b = Foo()
+ %dirty = %dirty and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
print("Hello World")
} else {
@@ -1241,18 +1265,22 @@
} else if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(text)) 0b0100 else 0b0010
}
- if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
- %dirty = %dirty or if (%composer.changed(color.value)) 0b00010000 else 0b1000
+ if (%changed and 0b00011000 === 0) {
+ %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(color.value)) 0b00010000 else 0b1000
}
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
%composer.startDefaults()
if (%default and 0b0010 !== 0) {
color = Companion.Unset
+ %dirty = %dirty and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
} else {
%composer.skipToGroupEnd()
@@ -1323,7 +1351,7 @@
%composer.startRestartGroup(%key)
if (%changed !== 0 || !%composer.skipping) {
val x = 123
- D(restartableFunction(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ D(composableLambda(%composer, <>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
if (%changed and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
Unit
} else {
@@ -1426,18 +1454,22 @@
%composer.startRestartGroup(%key)
val %dirty = %changed
val x = x
- if (%default and 0b0001 === 0 && %changed and 0b0110 === 0) {
- %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
+ if (%changed and 0b0110 === 0) {
+ %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
}
if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
%composer.startDefaults()
if (%default and 0b0001 !== 0) {
x = I(%composer, <>, 0)
+ %dirty = %dirty and 0b0110.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0001 !== 0) {
+ %dirty = %dirty and 0b0110.inv()
+ }
}
A(x, %composer, <>, 0b0110 and %dirty)
} else {
@@ -1500,10 +1532,14 @@
%composer.startDefaults()
if (%default and 0b0001 !== 0) {
x = Foo()
+ %dirty = %dirty and 0b0110.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0001 !== 0) {
+ %dirty = %dirty and 0b0110.inv()
+ }
}
A(x, %composer, <>, 0b0110 and %dirty)
} else {
@@ -1565,13 +1601,21 @@
}
if (%default and 0b1000 !== 0) {
d = Foo()
+ %dirty = %dirty and 0b000110000000.inv()
}
if (%default and 0b00010000 !== 0) {
e = emptyList()
+ %dirty = %dirty and 0b011000000000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b1000 !== 0) {
+ %dirty = %dirty and 0b000110000000.inv()
+ }
+ if (%default and 0b00010000 !== 0) {
+ %dirty = %dirty and 0b011000000000.inv()
+ }
}
A(a, b, c, d, e, %composer, <>, 0b0110 and %dirty or 0b00011000 and %dirty or 0b01100000 and %dirty or 0b000110000000 and %dirty or 0b011000000000 and %dirty)
} else {
@@ -1679,7 +1723,7 @@
}
""",
"""
- val unstableUnused: Function4<Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val unstableUnused: Function4<Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
%dirty = %dirty or 0b0110
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
@@ -1688,11 +1732,11 @@
%composer.skipToGroupEnd()
}
}
- val unstableUsed: Function4<Foo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val unstableUsed: Function4<Foo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
print(x)
}
- val stableUnused: Function4<StableFoo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val stableUnused: Function4<StableFoo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
%dirty = %dirty or 0b0110
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
@@ -1701,7 +1745,7 @@
%composer.skipToGroupEnd()
}
}
- val stableUsed: Function4<StableFoo, Composer<*>, Int, Int, Unit> = restartableFunctionInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
+ val stableUsed: Function4<StableFoo, Composer<*>, Int, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(<this>)) 0b0100 else 0b0010
@@ -1742,13 +1786,13 @@
%dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
}
if (%dirty and 0b0011 xor 0b0010 !== 0 || !%composer.skipping) {
- Provide(restartableFunction(%composer, <>, true) { y: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+ Provide(composableLambda(%composer, <>, true) { y: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(y)) 0b0100 else 0b0010
}
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
- Provide(restartableFunction(%composer, <>, true) { z: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
+ Provide(composableLambda(%composer, <>, true) { z: Int, %composer: Composer<*>?, %key: Int, %changed: Int ->
val %dirty = %changed
if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(z)) 0b0100 else 0b0010
@@ -2341,8 +2385,8 @@
} else if (%changed and 0b0110 === 0) {
%dirty = %dirty or if (%composer.changed(wontChange)) 0b0100 else 0b0010
}
- if (%default and 0b0010 === 0 && %changed and 0b00011000 === 0) {
- %dirty = %dirty or if (%composer.changed(mightChange)) 0b00010000 else 0b1000
+ if (%changed and 0b00011000 === 0) {
+ %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(mightChange)) 0b00010000 else 0b1000
}
if (%dirty and 0b1011 xor 0b1010 !== 0 || !%composer.skipping) {
if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -2352,10 +2396,14 @@
}
if (%default and 0b0010 !== 0) {
mightChange = AmbientColor.current
+ %dirty = %dirty and 0b00011000.inv()
}
%composer.endDefaults()
} else {
%composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
}
A(wontChange, %composer, <>, 0b0110 and %dirty)
A(mightChange, %composer, <>, 0b0110 and %dirty shr 0b0010)
@@ -2397,4 +2445,73 @@
}
"""
)
+
+ @Test
+ fun testDefaultsIssue(): Unit = comparisonPropagation(
+ """
+ """,
+ """
+ import androidx.ui.core.Modifier
+ import androidx.ui.unit.Dp
+ import androidx.compose.emptyContent
+
+ @Composable
+ fun Box2(
+ modifier: Modifier = Modifier,
+ paddingStart: Dp = Dp.Unspecified,
+ children: @Composable () -> Unit = emptyContent()
+ ) {
+
+ }
+ """,
+ """
+ @Composable
+ fun Box2(modifier: Modifier?, paddingStart: Dp, children: Function3<Composer<*>, Int, Int, Unit>?, %composer: Composer<*>?, %key: Int, %changed: Int, %default: Int) {
+ %composer.startRestartGroup(%key)
+ val %dirty = %changed
+ val modifier = modifier
+ val paddingStart = paddingStart
+ val children = children
+ if (%default and 0b0001 !== 0) {
+ %dirty = %dirty or 0b0110
+ } else if (%changed and 0b0110 === 0) {
+ %dirty = %dirty or if (%composer.changed(modifier)) 0b0100 else 0b0010
+ }
+ if (%changed and 0b00011000 === 0) {
+ %dirty = %dirty or if (%default and 0b0010 === 0 && %composer.changed(paddingStart.value)) 0b00010000 else 0b1000
+ }
+ if (%default and 0b0100 !== 0) {
+ %dirty = %dirty or 0b01100000
+ } else if (%changed and 0b01100000 === 0) {
+ %dirty = %dirty or if (%composer.changed(children)) 0b01000000 else 0b00100000
+ }
+ if (%dirty and 0b00101011 xor 0b00101010 !== 0 || !%composer.skipping) {
+ if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
+ %composer.startDefaults()
+ if (%default and 0b0001 !== 0) {
+ modifier = Companion
+ }
+ if (%default and 0b0010 !== 0) {
+ paddingStart = Companion.Unspecified
+ %dirty = %dirty and 0b00011000.inv()
+ }
+ if (%default and 0b0100 !== 0) {
+ children = emptyContent()
+ }
+ %composer.endDefaults()
+ } else {
+ %composer.skipCurrentGroup()
+ if (%default and 0b0010 !== 0) {
+ %dirty = %dirty and 0b00011000.inv()
+ }
+ }
+ } else {
+ %composer.skipToGroupEnd()
+ }
+ %composer.endRestartGroup()?.updateScope { %composer: Composer<*>?, %key: Int, %force: Int ->
+ Box2(modifier, paddingStart, children, %composer, %key, %changed or 0b0001, %default)
+ }
+ }
+ """
+ )
}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt
index bb9c6a0..defb9ca 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxCrossModuleTests.kt
@@ -161,40 +161,6 @@
}
@Test
- fun testCrossinlineEmittable(): Unit = ensureSetup {
- compile(
- mapOf(
- "library module" to mapOf(
- "x/A.kt" to """
- package x
-
- import androidx.compose.Composable
- import android.widget.LinearLayout
-
- @Composable inline fun row(crossinline children: @Composable () -> Unit) {
- LinearLayout {
- children()
- }
- }
- """
- ),
- "Main" to mapOf(
- "b/B.kt" to """
- package b
-
- import androidx.compose.Composable
- import x.row
-
- @Composable fun Test() {
- row { }
- }
- """
- )
- )
- )
- }
-
- @Test
fun testParentNotInitializedBug(): Unit = ensureSetup {
compile(
mapOf(
@@ -743,6 +709,7 @@
import android.widget.*
import androidx.compose.*
+ import androidx.ui.viewinterop.emitView
import my.test.lib.*
var bar = 0
@@ -766,7 +733,10 @@
@Composable
fun Foo(bar: Int) {
InternalComp {
- TextView(text="${'$'}bar", id=$tvId)
+ emitView(::TextView) {
+ it.text="${'$'}bar"
+ it.id=$tvId
+ }
}
}
"""
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt
index 640f261..91f9d3e 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/KtxTransformationTest.kt
@@ -16,15 +16,12 @@
package androidx.compose.plugins.kotlin
-import org.junit.Ignore
-
class KtxTransformationTest : AbstractCodegenTest() {
- fun testObserveLowering() = ensureSetup { testCompile(
+ fun testObserveLowering() = ensureSetup { testCompileWithViewStubs(
"""
- import android.widget.Button
- import androidx.compose.*
- import androidx.ui.androidview.adapters.setOnClick
+ import androidx.compose.MutableState
+ import androidx.compose.mutableStateOf
@Composable
fun SimpleComposable() {
@@ -33,7 +30,11 @@
@Composable
fun FancyButton(state: MutableState<Int>) {
- Button(text=("Clicked "+state.value+" times"), onClick={state.value++}, id=42)
+ Button(
+ text=("Clicked "+state.value+" times"),
+ onClick={state.value++},
+ id=42
+ )
}
"""
) }
@@ -49,11 +50,8 @@
"""
) }
- fun testSingleViewCompose() = ensureSetup { testCompile(
+ fun testSingleViewCompose() = ensureSetup { testCompileWithViewStubs(
"""
- import androidx.compose.*
- import android.widget.*
-
class Foo {
@Composable
operator fun invoke() {
@@ -63,11 +61,8 @@
"""
) }
- fun testMultipleRootViewCompose() = ensureSetup { testCompile(
+ fun testMultipleRootViewCompose() = ensureSetup { testCompileWithViewStubs(
"""
- import androidx.compose.*
- import android.widget.*
-
class Foo {
@Composable
operator fun invoke() {
@@ -79,11 +74,8 @@
"""
) }
- fun testNestedViewCompose() = ensureSetup { testCompile(
+ fun testNestedViewCompose() = ensureSetup { testCompileWithViewStubs(
"""
- import androidx.compose.*
- import android.widget.*
-
class Foo {
@Composable
operator fun invoke() {
@@ -133,11 +125,8 @@
"""
) }
- fun testViewAndComposites() = ensureSetup { testCompile(
+ fun testViewAndComposites() = ensureSetup { testCompileWithViewStubs(
"""
- import androidx.compose.*
- import android.widget.*
-
@Composable
fun Bar() {}
@@ -231,28 +220,8 @@
"""
) }
- fun testExtensionFunctions() = ensureSetup { testCompile(
+ fun testChildrenWithTypedParameters() = ensureSetup { testCompileWithViewStubs(
"""
-
- import androidx.compose.*
- import android.widget.*
-
- fun LinearLayout.setSomeExtension(x: Int) {
- }
- class X {
- @Composable
- operator fun invoke() {
- LinearLayout(someExtension=123)
- }
- }
- """
- ) }
-
- fun testChildrenWithTypedParameters() = ensureSetup { testCompile(
- """
- import android.widget.*
- import androidx.compose.*
-
@Composable fun HelperComponent(
children: @Composable (title: String, rating: Int) -> Unit
) {
@@ -273,11 +242,8 @@
"""
) }
- fun testChildrenCaptureVariables() = ensureSetup { testCompile(
+ fun testChildrenCaptureVariables() = ensureSetup { testCompileWithViewStubs(
"""
- import android.widget.*
- import androidx.compose.*
-
@Composable fun HelperComponent(children: @Composable () -> Unit) {
}
@@ -352,11 +318,8 @@
)
}
- fun testChildrenOfNativeView() = ensureSetup { testCompile(
+ fun testChildrenOfNativeView() = ensureSetup { testCompileWithViewStubs(
"""
- import android.widget.*
- import androidx.compose.*
-
class MainComponent {
@Composable
operator fun invoke() {
@@ -369,11 +332,8 @@
"""
) }
- fun testIrSpecial() = ensureSetup { testCompile(
+ fun testIrSpecial() = ensureSetup { testCompileWithViewStubs(
"""
- import android.widget.*
- import androidx.compose.*
-
@Composable fun HelperComponent(children: @Composable () -> Unit) {}
class MainComponent {
@@ -467,17 +427,6 @@
"""
) }
- fun testPackageQualifiedTags() = ensureSetup { testCompile(
- """
- import androidx.compose.*
-
- @Composable
- fun run() {
- android.widget.TextView(text="bar")
- }
- """
- ) }
-
fun testLocalLambda() = ensureSetup { testCompile(
"""
import androidx.compose.*
@@ -601,11 +550,8 @@
"""
) }
- fun testKtxLambdaInIfElse() = ensureSetup { testCompile(
+ fun testKtxLambdaInIfElse() = ensureSetup { testCompileWithViewStubs(
"""
- import androidx.compose.*
- import android.widget.TextView
-
@Composable
fun foo(x: Boolean) {
val lambda = @Composable { TextView(text="Hello World") }
@@ -648,52 +594,6 @@
)
}
- fun testKtxEmittable() = ensureSetup { testCompileEmittable(
- """
-
- open class MockEmittable: Emittable {
- override fun emitInsertAt(index: Int, instance: Emittable) {}
- override fun emitRemoveAt(index: Int, count: Int) {}
- override fun emitMove(from: Int, to: Int, count: Int) {}
- }
-
- class MyEmittable: MockEmittable() {
- var a: Int = 1
- }
-
- class Comp {
- @Composable
- fun Example() {
- MyEmittable(a=2)
- }
- }
- """
- ) }
-
- @Ignore("b/150394471")
- fun xtestKtxCompoundEmittable() = ensureSetup { testCompileEmittable(
- """
- open class MockEmittable: Emittable {
- override fun emitInsertAt(index: Int, instance: Emittable) {}
- override fun emitRemoveAt(index: Int, count: Int) {}
- override fun emitMove(from: Int, to: Int, count: Int) {}
- }
-
- class MyEmittable: MockEmittable() {
- var a: Int = 1
- }
-
- @Composable fun Test() {
- MyEmittable(a=1) {
- MyEmittable(a=2)
- MyEmittable(a=3)
- MyEmittable(a=4)
- MyEmittable(a=5)
- }
- }
- """
- ) }
-
fun testInvocableObject() = ensureSetup { testCompile(
"""
import androidx.compose.*
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt
index 749ca47..a17847f 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/LambdaMemoizationTests.kt
@@ -664,8 +664,7 @@
@Composable
fun Example(model: String) {
workToBeRepeated()
- @OptIn(androidx.compose.ExperimentalComposeApi::class)
- Wrapper @Untracked {
+ Wrapper @ComposableContract(tracked = false) {
workToBeAvoided()
ValidateModel(model)
}
@@ -736,7 +735,11 @@
@Composable
fun TestHost() {
println("START: Iteration - ${'$'}iterations")
- Button(id=42, onClick=invalidate)
+ val recompose = invalidate
+ emitView(::Button) {
+ it.id=42
+ it.setOnClickListener(View.OnClickListener { recompose() })
+ }
Example("Iteration ${'$'}iterations")
println("END : Iteration - ${'$'}iterations")
validate()
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt
index a9aed55..b5a129d 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/RobolectricComposeTester.kt
@@ -23,9 +23,11 @@
import android.widget.LinearLayout
import androidx.compose.Composer
import androidx.compose.Composition
+import androidx.compose.ExperimentalComposeApi
import androidx.compose.Recomposer
import androidx.compose.compositionFor
-import androidx.ui.node.UiComposer
+import androidx.ui.core.ContextAmbient
+import androidx.ui.node.UiApplier
import org.robolectric.Robolectric
import org.robolectric.RuntimeEnvironment
import org.robolectric.Shadows.shadowOf
@@ -77,12 +79,31 @@
val root = activity.root
scheduler.advanceToLastPostedRunnable()
- val composition = compositionFor(root, Recomposer.current()) { slotTable, recomposer ->
- UiComposer(activity, root, slotTable, recomposer)
+ val startProviders = Composer::class.java.methods.first {
+ it.name.startsWith("startProviders")
+ }
+ val endProviders = Composer::class.java.methods.first {
+ it.name.startsWith("endProviders")
}
val setContentMethod = Composition::class.java.methods.first { it.name == "setContent" }
+ startProviders.isAccessible = true
+ endProviders.isAccessible = true
setContentMethod.isAccessible = true
- fun setContent() { setContentMethod.invoke(composition, composable) }
+
+ val realComposable: (Composer<*>, Int, Int) -> Unit = { composer, _, _ ->
+ startProviders.invoke(
+ composer,
+ listOf(ContextAmbient provides root.context).toTypedArray()
+ )
+ composable(composer, 0, 0)
+ endProviders.invoke(composer)
+ }
+
+ @OptIn(ExperimentalComposeApi::class)
+ val composition = compositionFor(root, UiApplier(root), Recomposer.current())
+ fun setContent() {
+ setContentMethod.invoke(composition, realComposable)
+ }
setContent()
scheduler.advanceToLastPostedRunnable()
block(activity)
diff --git a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt
index 5884864..5181116 100644
--- a/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt
+++ b/compose/compose-compiler-hosted/integration-tests/src/test/java/androidx/compose/plugins/kotlin/analysis/ComposableCheckerTests.kt
@@ -60,10 +60,12 @@
fun testComposableReporting001() {
checkFail("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
fun myStatelessFunctionalComponent() {
- TextView(text="Hello World!")
+ Leaf()
}
fun foo() {
@@ -72,11 +74,13 @@
""")
check("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
@Composable
fun myStatelessFunctionalComponent() {
- TextView(text="Hello World!")
+ Leaf()
}
@Composable
@@ -89,17 +93,21 @@
fun testComposableReporting002() {
checkFail("""
import androidx.compose.*;
- import android.widget.TextView;
- val myLambda1 = { TextView(text="Hello World!") }
- val myLambda2: () -> Unit = { TextView(text="Hello World!") }
+ @Composable
+ fun Leaf() {}
+
+ val myLambda1 = { Leaf() }
+ val myLambda2: () -> Unit = { Leaf() }
""")
check("""
import androidx.compose.*;
- import android.widget.TextView;
- val myLambda1 = @Composable { TextView(text="Hello World!") }
- val myLambda2: @Composable ()->Unit = { TextView(text="Hello World!") }
+ @Composable
+ fun Leaf() {}
+
+ val myLambda1 = @Composable { Leaf() }
+ val myLambda2: @Composable ()->Unit = { Leaf() }
""")
}
@@ -114,27 +122,16 @@
""")
}
- fun testComposableReporting004() {
- check("""
- import androidx.compose.*;
- import android.widget.TextView;
-
- @Composable
- fun foo() {
- val myRandomLambda = { <!NONE_APPLICABLE!>TextView<!>(text="Hello World!") }
- System.out.println(myRandomLambda)
- }
- """)
- }
-
fun testComposableReporting006() {
checkFail("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
fun foo() {
val bar = {
- TextView()
+ Leaf()
}
bar()
System.out.println(bar)
@@ -142,12 +139,14 @@
""")
check("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
@Composable
fun foo() {
val bar = @Composable {
- TextView()
+ Leaf()
}
bar()
System.out.println(bar)
@@ -209,35 +208,6 @@
""")
}
- fun testComposableReporting016() {
- check("""
- import androidx.compose.*;
-
- <!WRONG_ANNOTATION_TARGET!>@Composable<!>
- class Noise() {}
- """)
-
- check("""
- import androidx.compose.*;
-
- val adHoc = <!WRONG_ANNOTATION_TARGET!>@Composable<!> object {
- var x: Int = 0
- var y: Int = 0
- }
- """)
-
- check("""
- import androidx.compose.*;
-
- open class Noise() {}
-
- val adHoc = <!WRONG_ANNOTATION_TARGET!>@Composable<!> object : Noise() {
- var x: Int = 0
- var y: Int = 0
- }
- """)
- }
-
fun testComposableReporting017() {
checkFail("""
import androidx.compose.*;
@@ -274,20 +244,23 @@
fun testComposableReporting018() {
checkFail("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
fun foo() {
- val myVariable: ()->Unit = @Composable { TextView(text="Hello World!") }
+ val myVariable: ()->Unit = @Composable { Leaf() }
System.out.println(myVariable)
}
""")
check("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
fun foo() {
- val myVariable: ()->Unit = <!TYPE_MISMATCH!>@Composable {
- TextView(text="Hello World!") }<!>
+ val myVariable: ()->Unit = <!TYPE_MISMATCH!>@Composable { Leaf() }<!>
System.out.println(myVariable)
}
""")
@@ -296,13 +269,15 @@
fun testComposableReporting021() {
check("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
@Composable
fun foo() {
val myList = listOf(1,2,3,4,5)
myList.forEach @Composable { value: Int ->
- TextView(text=value.toString())
+ Leaf()
System.out.println(value)
}
}
@@ -312,12 +287,14 @@
fun testComposableReporting022() {
checkFail("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
fun foo() {
val myList = listOf(1,2,3,4,5)
myList.forEach { value: Int ->
- TextView(text=value.toString())
+ Leaf()
System.out.println(value)
}
}
@@ -326,10 +303,13 @@
import androidx.compose.*;
import android.widget.TextView;
+ @Composable
+ fun Leaf() {}
+
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>() {
val myList = listOf(1,2,3,4,5)
myList.forEach @Composable { value: Int ->
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>TextView<!>(text=value.toString())
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE, COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Leaf<!>()
System.out.println(value)
}
}
@@ -339,12 +319,14 @@
fun testComposableReporting024() {
check("""
import androidx.compose.*;
+ import android.widget.LinearLayout
import androidx.ui.core.setViewContent
- import android.widget.TextView;
- import android.widget.LinearLayout;
+
+ @Composable
+ fun Leaf() {}
fun foo(ll: LinearLayout) {
- ll.setViewContent { TextView(text="Hello World!") }
+ ll.setViewContent { Leaf() }
}
""")
}
@@ -352,11 +334,13 @@
fun testComposableReporting025() {
check("""
import androidx.compose.*;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
@Composable
fun foo() {
- listOf(1,2,3,4,5).forEach { TextView(text="Hello World!") }
+ listOf(1,2,3,4,5).forEach { Leaf() }
}
""")
}
@@ -364,13 +348,17 @@
fun testComposableReporting026() {
check("""
import androidx.compose.*;
- import android.widget.LinearLayout;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
+
+ @Composable
+ fun Group(content: @Composable () -> Unit) { content() }
@Composable
fun foo() {
- LinearLayout {
- TextView(text="Hello Jim!")
+ Group {
+ Leaf()
}
}
""")
@@ -379,14 +367,18 @@
fun testComposableReporting027() {
check("""
import androidx.compose.*;
- import android.widget.LinearLayout;
- import android.widget.TextView;
+
+ @Composable
+ fun Leaf() {}
+
+ @Composable
+ fun Group(content: @Composable () -> Unit) { content() }
@Composable
fun foo() {
- LinearLayout {
+ Group {
listOf(1,2,3).forEach {
- TextView(text="Hello Jim!")
+ Leaf()
}
}
}
@@ -442,14 +434,16 @@
fun testComposableReporting032() {
check("""
import androidx.compose.*;
- import android.widget.TextView;
@Composable
fun MyComposable(children: @Composable ()->Unit) { children() }
+ @Composable
+ fun Leaf() {}
+
@Composable
fun foo() {
- MyComposable { TextView(text="Hello") }
+ MyComposable { Leaf() }
}
""")
}
@@ -457,14 +451,16 @@
fun testComposableReporting033() {
check("""
import androidx.compose.*;
- import android.widget.TextView;
@Composable
fun MyComposable(children: @Composable ()->Unit) { children() }
+ @Composable
+ fun Leaf() {}
+
@Composable
fun foo() {
- MyComposable(children={ TextView(text="Hello")})
+ MyComposable(children={ Leaf() })
}
""")
}
@@ -576,19 +572,19 @@
check(
"""
import androidx.compose.*
- import android.widget.TextView;
fun composeInto(l: @Composable ()->Unit) { System.out.println(l) }
fun Foo() {
composeInto {
- TextView(text="Hello World")
+ Baz()
}
}
fun Bar() {
Foo()
}
+ @Composable fun Baz() {}
"""
)
}
@@ -643,7 +639,7 @@
fun FancyButton() {}
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Noise<!>() {
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>FancyButton<!>()
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>FancyButton<!>()
}
""")
}
@@ -651,7 +647,6 @@
fun testComposableReporting044() {
check("""
import androidx.compose.*
- import android.widget.TextView;
typealias UNIT_LAMBDA = () -> Unit
@@ -678,23 +673,6 @@
""")
}
- fun testComposableReporting047() {
- check("""
- import androidx.compose.*
- import android.widget.LinearLayout;
-
- @Composable
- fun FancyButton() {}
-
- @Composable
- fun Foo() {
- LinearLayout {
- FancyButton()
- }
- }
- """)
- }
-
fun testComposableReporting048() {
// Type inference for non-null @Composable lambdas
checkFail("""
@@ -889,7 +867,7 @@
@Composable fun foo(): Int = 123
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>App<!>() {
- val x = <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>()
+ val x = <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>()
print(x)
}
""")
@@ -902,25 +880,25 @@
@Composable fun Foo() {}
val y: Any <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>get() =
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 1 }<!>
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 1 }<!>
fun App() {
val x = object {
val a <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>get() =
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 2 }<!>
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 2 }<!>
@Composable val c get() = state { 4 }
@Composable fun bar() { Foo() }
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>() {
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
}
}
class Bar {
val b <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>get() =
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 6 }<!>
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!> { 6 }<!>
@Composable val c get() = state { 7 }
}
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Bam<!>() {
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
}
@Composable fun Boo() {
Foo()
@@ -942,7 +920,7 @@
<!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!><!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>state<!><!> { 2 }<!>
@Composable val c get() = state { 4 }
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>foo<!>() {
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
}
@Composable fun bar() { Foo() }
}
@@ -952,7 +930,7 @@
@Composable val c get() = state { 7 }
}
fun <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Bam<!>() {
- <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
+ <!COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE!>Foo<!>()
}
@Composable fun Boo() {
Foo()
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt
index 90495b6..f5ec4af 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableAnnotationChecker.kt
@@ -36,7 +36,6 @@
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
-import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotatedExpression
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtCallExpression
@@ -63,8 +62,6 @@
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
-import org.jetbrains.kotlin.psi.KtFunctionLiteral
-import org.jetbrains.kotlin.psi.KtLambdaArgument
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
@@ -83,7 +80,6 @@
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.upperIfFlexible
import org.jetbrains.kotlin.util.OperatorNameConventions
-import org.jetbrains.kotlin.utils.addToStdlib.cast
open class ComposableAnnotationChecker : CallChecker, DeclarationChecker,
AdditionalTypeChecker, AdditionalAnnotationChecker, StorageComponentContainerContributor {
@@ -140,10 +136,6 @@
}
val psi = unwrappedDescriptor.findPsi() as? KtElement
psi?.let { trace.bindingContext.get(COMPOSABLE_ANALYSIS, it)?.let { return it } }
- if (unwrappedDescriptor.name == Name.identifier("compose") &&
- unwrappedDescriptor.containingDeclaration is ClassDescriptor &&
- ComposeUtils.isComposeComponent(unwrappedDescriptor.containingDeclaration)
- ) return Composability.MARKED
var composability = Composability.NOT_COMPOSABLE
if (trace.bindingContext.get(
INFERRED_COMPOSABLE_DESCRIPTOR,
@@ -167,9 +159,6 @@
is AnonymousFunctionDescriptor -> {
if (unwrappedDescriptor.hasComposableAnnotation()) composability =
Composability.MARKED
- if (psi is KtFunctionLiteral && psi.isEmitInline(trace.bindingContext)) {
- composability = Composability.MARKED
- }
}
is PropertyGetterDescriptor ->
if (unwrappedDescriptor.correspondingProperty.hasComposableAnnotation())
@@ -251,7 +240,6 @@
reportElement: KtExpression
) {
when (resolvedCall?.candidateDescriptor) {
- is ComposableEmitDescriptor,
is ComposablePropertyDescriptor,
is ComposableFunctionDescriptor -> {
localFcs = true
@@ -314,13 +302,11 @@
Composability.NOT_COMPOSABLE
if (element is KtClass) {
- val descriptor = trace.bindingContext.get(BindingContext.CLASS, element)
- ?: error("Element class context not found")
val annotationEntry = element.annotationEntries.singleOrNull {
trace.bindingContext.get(BindingContext.ANNOTATION, it)?.isComposableAnnotation
?: false
}
- if (annotationEntry != null && !ComposeUtils.isComposeComponent(descriptor)) {
+ if (annotationEntry != null) {
trace.report(
Errors.WRONG_ANNOTATION_TARGET.on(
annotationEntry,
@@ -328,9 +314,6 @@
)
)
}
- if (ComposeUtils.isComposeComponent(descriptor)) {
- composability += Composability.MARKED
- }
}
if (element is KtParameter) {
val composableAnnotation = element
@@ -380,15 +363,6 @@
}
if (element is KtLambdaExpression || element is KtFunction) {
- val associatedCall = parent?.parent as? KtCallExpression
-
- if (associatedCall != null && parent is KtLambdaArgument) {
- val resolvedCall = associatedCall.getResolvedCall(trace.bindingContext)
- if (resolvedCall?.candidateDescriptor is ComposableEmitDescriptor) {
- composability += Composability.MARKED
- }
- }
-
composability = analyzeFunctionContents(trace, element, composability)
}
@@ -415,19 +389,13 @@
val trace = context.trace
val element = descriptor.findPsi()
if (element is KtClass) {
- val classDescriptor =
- trace.bindingContext.get(
- BindingContext.CLASS,
- element
- ) ?: error("Element class context not found")
val composableAnnotationEntry = element.annotationEntries.singleOrNull {
trace.bindingContext.get(
BindingContext.ANNOTATION,
it
)?.isComposableAnnotation ?: false
}
- if (composableAnnotationEntry != null &&
- !ComposeUtils.isComposeComponent(classDescriptor)) {
+ if (composableAnnotationEntry != null) {
trace.report(
Errors.WRONG_ANNOTATION_TARGET.on(
composableAnnotationEntry,
@@ -480,19 +448,6 @@
)
if (isInlineable) return
- if (expression.parent is KtLambdaArgument) {
- val callDescriptor = expression
- .parent
- ?.parent
- ?.cast<KtCallExpression>()
- ?.getResolvedCall(c.trace.bindingContext)
- ?.candidateDescriptor
-
- if (callDescriptor is ComposableEmitDescriptor) {
- return
- }
- }
-
val reportOn =
if (expression.parent is KtAnnotatedExpression)
expression.parent as KtExpression
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableEmitDescriptor.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableEmitDescriptor.kt
deleted file mode 100644
index 920ab4d..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposableEmitDescriptor.kt
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.plugins.kotlin
-
-import org.jetbrains.kotlin.builtins.DefaultBuiltIns
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.SourceElement
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.descriptors.Visibilities
-import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
-import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.replace
-import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
-
-interface ComposableEmitMetadata {
- val composerMetadata: ComposerMetadata
- val emitCall: ResolvedCall<*>
- val hasChildren: Boolean
- val pivotals: List<String>
- val ctorCall: ResolvedCall<*>
- val ctorParams: List<String>
- val validations: List<ValidatedAssignment>
-}
-
-class ComposableEmitDescriptor(
- override val composerMetadata: ComposerMetadata,
- override val emitCall: ResolvedCall<*>,
- override val hasChildren: Boolean,
- override val pivotals: List<String>,
- override val ctorCall: ResolvedCall<*>,
- override val ctorParams: List<String>,
- override val validations: List<ValidatedAssignment>,
- containingDeclaration: DeclarationDescriptor,
- original: SimpleFunctionDescriptor?,
- annotations: Annotations,
- name: Name,
- kind: CallableMemberDescriptor.Kind,
- source: SourceElement
-) : ComposableEmitMetadata, SimpleFunctionDescriptorImpl(
- containingDeclaration,
- original,
- annotations,
- name,
- kind,
- source
-) {
-
- companion object {
- fun build(
- hasChildren: Boolean,
- emitCall: ResolvedCall<*>,
- pivotals: List<String>,
- ctorCall: ResolvedCall<*>,
- ctorParams: List<String>,
- validations: List<ValidatedAssignment>,
- composerMetadata: ComposerMetadata,
- name: Name
- ): ComposableEmitDescriptor {
-
- val builtIns = DefaultBuiltIns.Instance
-
- val resolvedCall = ctorCall
-
- val original = resolvedCall.resultingDescriptor as? SimpleFunctionDescriptor
-
- val descriptor = ComposableEmitDescriptor(
- composerMetadata,
- emitCall,
- hasChildren,
- pivotals,
- ctorCall,
- ctorParams,
- validations,
- emitCall.candidateDescriptor.containingDeclaration,
- original,
- Annotations.EMPTY,
- name,
- CallableMemberDescriptor.Kind.SYNTHESIZED,
- SourceElement.NO_SOURCE
- )
-
- val valueArgs = mutableListOf<ValueParameterDescriptor>()
- val paramSet = mutableSetOf<String>()
-
- for (paramName in ctorParams) {
- if (paramSet.contains(paramName)) continue
- val param = resolvedCall.resultingDescriptor.valueParameters.find {
- it.name.identifier == paramName
- } ?: continue
-
- paramSet.add(paramName)
- valueArgs.add(
- ValueParameterDescriptorImpl(
- descriptor, null, valueArgs.size,
- Annotations.EMPTY,
- param.name,
- param.type, false,
- false,
- false, null,
- SourceElement.NO_SOURCE
- )
- )
- }
-
- for (validation in validations) {
- if (paramSet.contains(validation.name)) continue
- paramSet.add(validation.name)
- valueArgs.add(
- ValueParameterDescriptorImpl(
- descriptor,
- null,
- valueArgs.size,
- Annotations.EMPTY,
- Name.identifier(validation.name),
- validation.type,
- false,
- false,
- false,
- null,
- SourceElement.NO_SOURCE
- )
- )
- }
-
- val unitLambdaType = builtIns.getFunction(
- 0
- ).defaultType.replace(
- listOf(builtIns.unitType.asTypeProjection())
- )
- // NOTE(lmr): it's actually kind of important that this is *not* a composable lambda,
- // so that the observe patcher doesn't insert an observe scope.
- // In the future, we should reconsider how this is done since semantically a composable
- // lambda is more correct here. I tried, but had trouble passing enough information to
- // the observe patcher so it knew not to do this.
- /*.makeComposable(scopeTower.module)*/
- if (hasChildren) {
- valueArgs.add(
- EmitChildrenValueParameterDescriptor(
- descriptor, null, valueArgs.size,
- Annotations.EMPTY,
- Name.identifier("\$CHILDREN"),
- unitLambdaType, false,
- false,
- false, null,
- SourceElement.NO_SOURCE
- )
- )
- }
-
- descriptor.initialize(
- null,
- null,
- mutableListOf(),
- valueArgs,
- builtIns.unitType,
- Modality.FINAL,
- Visibilities.DEFAULT_VISIBILITY
- )
-
- return descriptor
- }
- }
-}
-
-class EmitChildrenValueParameterDescriptor(
- containingDeclaration: CallableDescriptor,
- original: ValueParameterDescriptor?,
- index: Int,
- annotations: Annotations,
- name: Name,
- outType: KotlinType,
- declaresDefaultValue: Boolean,
- isCrossinline: Boolean,
- isNoinline: Boolean,
- varargElementType: KotlinType?,
- source: SourceElement
-) : ValueParameterDescriptorImpl(
- containingDeclaration,
- original,
- index,
- annotations,
- name,
- outType,
- declaresDefaultValue,
- isCrossinline,
- isNoinline,
- varargElementType,
- source
-)
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt
index f643a21..843f682 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeCallResolutionInterceptorExtension.kt
@@ -16,42 +16,29 @@
package androidx.compose.plugins.kotlin
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.extensions.internal.CallResolutionInterceptorExtension
import org.jetbrains.kotlin.incremental.components.LookupLocation
-import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction
-import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
-import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionMutableResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
-import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
-import org.jetbrains.kotlin.types.KotlinType
typealias Candidate = NewResolutionOldInference.MyCandidate
@@ -88,18 +75,21 @@
when (val descriptor = underlying.candidateDescriptor) {
is FunctionDescriptor -> ComposableFunctionDescriptor(descriptor)
is PropertyDescriptor -> ComposablePropertyDescriptorImpl(descriptor)
- else -> error("Expected FunctionDescriptor or PropertyDescriptor, found $descriptor")
+ else -> descriptor
}
override fun getCandidateDescriptor(): T = composableCandidateDescriptor as T
override fun getResultingDescriptor(): T {
return when (val descriptor = underlying.resultingDescriptor) {
is FunctionDescriptor -> ComposableFunctionDescriptor(descriptor)
is PropertyDescriptor -> ComposablePropertyDescriptorImpl(descriptor)
- else -> error("Expected FunctionDescriptor or PropertyDescriptor, found $descriptor")
+ else -> descriptor
} as T
}
}
+// TODO(lmr): This class is only needed for the syntax highlighting for composable calls right
+// now. The ComposableFunctionDescriptors are not otherwise needed. We should refactor the
+// syntax highlighting plugin ASAP so that we can get rid of this plugin.
@Suppress("INVISIBLE_REFERENCE", "EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints::class)
open class ComposeCallResolutionInterceptorExtension : CallResolutionInterceptorExtension {
@@ -112,67 +102,36 @@
kind: NewResolutionOldInference.ResolutionKind,
tracing: TracingStrategy
): Collection<Candidate> {
- if (callResolver == null) throw IllegalArgumentException("Call resolver must be non-null")
-
if (candidates.isEmpty()) return candidates
- val bindingContext = context.trace.bindingContext
- val call = context.call
- val shouldIgnore = bindingContext[
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- call
- ] ?: false
- if (shouldIgnore) return candidates
-
+ val others = mutableListOf<Candidate>()
val composables = mutableListOf<Candidate>()
- val nonComposablesNonConstructors = mutableListOf<Candidate>()
- val alreadyInterceptedCandidates = mutableListOf<Candidate>()
- val constructors = mutableListOf<Candidate>()
-
- var needToLookupComposer = false
for (candidate in candidates) {
val resolvedCall = candidate.resolvedCall
val candidateDescriptor = resolvedCall.candidateDescriptor
when {
candidateDescriptor is ComposableFunctionDescriptor -> {
- alreadyInterceptedCandidates.add(candidate)
- }
- candidateDescriptor is ComposableEmitDescriptor -> {
- alreadyInterceptedCandidates.add(candidate)
+ others.add(candidate)
}
resolvedCall is VariableAsFunctionResolvedCall &&
resolvedCall.variableCall
.candidateDescriptor
.type
.hasComposableAnnotation() -> {
- needToLookupComposer = true
composables.add(candidate)
}
resolvedCall.candidateDescriptor.hasComposableAnnotation() -> {
- needToLookupComposer = true
composables.add(candidate)
}
- resolvedCall.candidateDescriptor is ConstructorDescriptor -> {
- needToLookupComposer = true
- constructors.add(candidate)
- }
- else -> nonComposablesNonConstructors.add(candidate)
+ else -> others.add(candidate)
}
}
- // If none of the candidates are composable or constructors, then it's unnecessary for us
- // to do any work at all, since it will never be anything we intercept
- if (!needToLookupComposer) return candidates
-
- if (!isInComposableScope(context)) return candidates
-
- // NOTE(lmr): I'm not implementing emittable interception here, since I believe it is not
- // needed. So in this case we just pass constructors right through, untouched.
- return nonComposablesNonConstructors +
- constructors +
- alreadyInterceptedCandidates +
- composables.map { ComposableCandidate(it) }
+ return when {
+ composables.isEmpty() || !isInComposableScope(context) -> candidates
+ else -> others + composables.map { ComposableCandidate(it) }
+ }
}
override fun interceptCandidates(
@@ -184,128 +143,22 @@
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> {
- val element = resolutionContext.call.callElement as KtExpression
- val project = element.project
- if (callResolver == null) throw IllegalArgumentException("Call resolver must be non-null")
-
- if (candidates.isEmpty()) return candidates
- val bindingContext = resolutionContext.trace.bindingContext
- val call = resolutionContext.call
- val shouldIgnore = bindingContext[
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- call
- ] ?: false
-
- if (shouldIgnore) return candidates
-
+ val others = mutableListOf<FunctionDescriptor>()
val composables = mutableListOf<FunctionDescriptor>()
- val nonComposablesNonConstructors = mutableListOf<FunctionDescriptor>()
- val constructors = mutableListOf<ConstructorDescriptor>()
-
- var needToLookupComposer = false
for (candidate in candidates) {
when {
candidate.hasComposableAnnotation() -> {
- needToLookupComposer = true
composables.add(candidate)
}
- candidate is ConstructorDescriptor -> {
- needToLookupComposer = true
- constructors.add(candidate)
- }
- else -> nonComposablesNonConstructors.add(candidate)
+ else -> others.add(candidate)
}
}
- // If none of the candidates are composable or constructors, then it's unnecessary for us
- // to do any work at all, since it will never be anything we intercept
- if (!needToLookupComposer) return candidates
-
- // If there are no constructors, then all of the candidates are either composables or
- // non-composable functions, and we follow normal resolution rules.
- if (constructors.isEmpty()) {
- // we wrap the composable descriptors into a ComposableFunctionDescriptor so we know
- // to intercept it in the backend.
- return nonComposablesNonConstructors + composables.map {
- ComposableFunctionDescriptor(it)
- }
+ return when {
+ composables.isEmpty() || !isInComposableScope(resolutionContext) -> candidates
+ else -> others + composables.map { ComposableFunctionDescriptor(it) }
}
-
- if (!isInComposableScope(resolutionContext)) return candidates
-
- val composerType = callResolver.findComposerCallAndDescriptor(resolutionContext)
- ?: return nonComposablesNonConstructors + constructors
-
- val psiFactory = KtPsiFactory(project, markGenerated = false)
-
- // If we made it this far, we need to check and see if the constructors qualify as emit
- // calls instead of constructor calls. First, we need to look at the composer to see
- // what kinds of "emittables" it accepts.
- // We cache the metadata into a writeable slice based on the descriptor
- val composerMetadata = ComposerMetadata.getOrBuild(
- composerType,
- callResolver,
- psiFactory,
- resolutionContext
- )
-
- val emittables = constructors.filter {
- composerMetadata.isEmittable(it.returnType) && !it.returnType.isAbstract()
- }
- val hasEmittableCandidate = emittables.isNotEmpty()
-
- // if none of the constructors are emittables, then all of the candidates are valid
- if (!hasEmittableCandidate) {
- return nonComposablesNonConstructors + constructors + composables.map {
- ComposableFunctionDescriptor(it)
- }
- }
-
- // since some of the constructors are emittables, we fall back to resolving using the
- // emit resolver.
- val emitResolver = ComposeEmitResolver(
- callResolver,
- project,
- composerMetadata
- )
-
- val emitCandidates = emitResolver.resolveCandidates(
- call,
- emittables,
- name,
- resolutionContext
- )
-
- return nonComposablesNonConstructors +
- composables.map {
- ComposableFunctionDescriptor(it)
- } +
- constructors.filter { !composerMetadata.isEmittable(it.returnType) } +
- emitCandidates
- }
-
- private fun CallResolver.findComposerCallAndDescriptor(
- context: BasicCallResolutionContext
- ): KotlinType? {
- // use the call resolver to find any variable that would resolve with "composer" in scope.
- return resolveComposer(context)?.resultingDescriptor?.returnType
- // If there is no composer in scope, then we decide to fall back to the ViewComposer
- // as a default. When we are properly inferring the composer type, this step should no
- // longer be needed. This provides a better developer experience currently though since
- // developers won't be required to import the composer into scope.
- ?: context
- .scope
- .ownerDescriptor
- .module
- .findClassAcrossModuleDependencies(ClassId.topLevel(ComposeFqNames.UiComposer))
- ?.defaultType
- ?: context
- .scope
- .ownerDescriptor
- .module
- .findClassAcrossModuleDependencies(ClassId.topLevel(ComposeFqNames.Composer))
- ?.defaultType
}
private fun isInComposableScope(resolutionContext: BasicCallResolutionContext): Boolean {
@@ -352,52 +205,4 @@
}
return false
}
-
- private fun CallResolver.resolveVar(
- name: Name,
- context: BasicCallResolutionContext
- ): OverloadResolutionResults<CallableDescriptor> {
- val temporaryForVariable = TemporaryTraceAndCache.create(
- context,
- "trace to resolve variable",
- context.call.callElement as KtExpression
- )
- val call = makeCall(context.call.callElement)
- val contextForVariable = BasicCallResolutionContext.create(
- context.replaceTraceAndCache(temporaryForVariable),
- call,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call)
-
- )
- contextForVariable.trace.record(
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- call,
- true
- )
- return computeTasksAndResolveCall<CallableDescriptor>(
- contextForVariable,
- name,
- TracingStrategy.EMPTY,
- NewResolutionOldInference.ResolutionKind.Variable
- )
- }
-
- private fun CallResolver.resolveComposer(context: BasicCallResolutionContext):
- ResolvedCall<CallableDescriptor>? {
-
- // The composer is currently resolved as whatever is currently in scope with the name "composer".
- val resolvedComposer = resolveVar(KtxNameConventions.COMPOSER, context)
-
- if (!resolvedComposer.isSuccess) {
- return null
- }
-
- return resolvedComposer.resultingCall
- }
-
- private fun KotlinType.isAbstract(): Boolean {
- val modality = (constructor.declarationDescriptor as? ClassDescriptor)?.modality
- return modality == Modality.ABSTRACT || modality == Modality.SEALED
- }
}
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeEmitResolver.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeEmitResolver.kt
deleted file mode 100644
index e5b8bf0..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeEmitResolver.kt
+++ /dev/null
@@ -1,1580 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.plugins.kotlin
-
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import com.intellij.lang.ASTNode
-import com.intellij.openapi.project.Project
-import com.intellij.psi.impl.source.tree.LeafPsiElement
-import com.intellij.util.SmartList
-import org.jetbrains.kotlin.builtins.DefaultBuiltIns
-import org.jetbrains.kotlin.builtins.createFunctionType
-import org.jetbrains.kotlin.builtins.extractParameterNameFromFunctionTypeArgument
-import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
-import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
-import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
-import org.jetbrains.kotlin.builtins.isExtensionFunctionType
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.ClassKind
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
-import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
-import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.descriptors.VariableDescriptor
-import org.jetbrains.kotlin.descriptors.Visibilities
-import org.jetbrains.kotlin.descriptors.annotations.Annotations
-import org.jetbrains.kotlin.diagnostics.Severity
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi.Call
-import org.jetbrains.kotlin.psi.KtElement
-import org.jetbrains.kotlin.psi.KtExpression
-import org.jetbrains.kotlin.psi.KtLambdaArgument
-import org.jetbrains.kotlin.psi.KtPsiFactory
-import org.jetbrains.kotlin.psi.KtQualifiedExpression
-import org.jetbrains.kotlin.psi.KtReferenceExpression
-import org.jetbrains.kotlin.psi.KtSimpleNameExpression
-import org.jetbrains.kotlin.psi.ValueArgument
-import org.jetbrains.kotlin.psi.ValueArgumentName
-import org.jetbrains.kotlin.builtins.isFunctionType
-import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
-import org.jetbrains.kotlin.descriptors.Modality
-import org.jetbrains.kotlin.descriptors.SourceElement
-import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
-import org.jetbrains.kotlin.psi.KtTypeArgumentList
-import org.jetbrains.kotlin.psi.KtTypeProjection
-import org.jetbrains.kotlin.psi.KtValueArgumentList
-import org.jetbrains.kotlin.psi.LambdaArgument
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.BindingTrace
-import org.jetbrains.kotlin.resolve.DescriptorFactory
-import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
-import org.jetbrains.kotlin.resolve.calls.CallResolver
-import org.jetbrains.kotlin.resolve.calls.checkers.UnderscoreUsageChecker
-import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
-import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
-import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
-import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
-import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus
-import org.jetbrains.kotlin.resolve.calls.model.ArgumentUnmapped
-import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl
-import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
-import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
-import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
-import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
-import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
-import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
-import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate
-import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
-import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyImpl
-import org.jetbrains.kotlin.resolve.calls.tower.NewResolutionOldInference
-import org.jetbrains.kotlin.resolve.calls.util.CallMaker
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
-import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
-import org.jetbrains.kotlin.resolve.scopes.MemberScope
-import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
-import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
-import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
-import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
-import org.jetbrains.kotlin.resolve.scopes.receivers.TypeAliasQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.TypeParameterQualifier
-import org.jetbrains.kotlin.resolve.scopes.receivers.expression
-import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
-import org.jetbrains.kotlin.resolve.scopes.utils.findFirstFromMeAndParent
-import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
-import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
-import org.jetbrains.kotlin.synthetic.isVisibleOutside
-import org.jetbrains.kotlin.types.ErrorUtils
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.TypeConstructor
-import org.jetbrains.kotlin.types.TypeSubstitutor
-import org.jetbrains.kotlin.types.TypeUtils
-import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
-import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl
-import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
-import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
-import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
-import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
-import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
-import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
-import org.jetbrains.kotlin.types.typeUtil.isUnit
-import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
-import java.util.Locale
-
-/**
- * This class is used to resolve a KTX Element to the corresponding set of calls on the composer, and the individual calls for
- * each attribute, etc.
- */
-class ComposeEmitResolver(
- callResolver: CallResolver,
- project: Project,
- private val composer: ComposerMetadata
-) {
-
- private val callResolver = NoInterceptionCallResolver(callResolver)
-
- private class TempParameterInfo(
- val attribute: AttributeInfo,
- val descriptor: DeclarationDescriptor
- )
-
- // NOTE(lmr): I am unsure of the performance consequences of using KtPsiFactory. it appears to create a file for every
- // call, which seems like something we definitely do not want, but it's also used in resolving for(..) loops, so
- // maybe it's not terrible.
- private val psiFactory = KtPsiFactory(project, markGenerated = false)
-
- private fun KotlinType.isEmittable() = composer.isEmittable(this)
-
- private fun KotlinType.isCompoundEmittable() = composer.isCompoundEmittable(this)
-
- private fun isImplicitConstructorParam(
- param: ValueParameterDescriptor,
- fn: CallableDescriptor
- ) = composer.isImplicitConstructorParam(param, fn)
-
- fun resolveCandidates(
- call: Call,
- candidates: Collection<FunctionDescriptor>,
- name: Name,
- resolutionContext: ResolutionContext<*>
- ): List<ComposableEmitDescriptor> {
- val context = ExpressionTypingContext.newContext(
- resolutionContext.trace,
- resolutionContext.scope,
- resolutionContext.dataFlowInfo,
- resolutionContext.expectedType,
- resolutionContext.languageVersionSettings,
- resolutionContext.dataFlowValueFactory
- )
- val openTagExpr = call.calleeExpression ?: error("Expected calleeExpression")
-
- val tmpTraceAndCache = TemporaryTraceAndCache.create(
- context,
- "trace for ktx tag",
- openTagExpr
- )
-
- val contextToUse = context.replaceTraceAndCache(tmpTraceAndCache)
-
- val attrInfos = mutableMapOf<String, AttributeInfo>()
-
- for (arg in call.valueArguments) {
- if (arg is KtLambdaArgument) continue
-
- // NOTE: emits *must* use all named parameters. If they don't, we will not resolve them.
- val argName = arg.getArgumentName() ?: return emptyList()
-
- val key = argName.referenceExpression
- val value = arg.getArgumentExpression()
- val identifier = argName.asName.asString()
-
- // NOTE: We don't have to check for duplicate argument names, that will be done elsewhere.
-
- // NOTE: We don't have to deal with punning. punning isn't supported in FCS.
-
- attrInfos[identifier] = AttributeInfo(
- value = value ?: error("expected a value expression"),
- key = key,
- name = identifier
- )
- }
-
- for (arg in call.functionLiteralArguments) {
- if (attrInfos.containsKey(CHILDREN_KEY))
- error("Only one children argument supported at a time")
- attrInfos[CHILDREN_KEY] =
- AttributeInfo(
- value = arg.getLambdaExpression() ?: error("expected a value expression"),
- key = null,
- name = CHILDREN_KEY
- )
- }
-
- val receiver = resolveReceiver(openTagExpr, contextToUse)
-
- attrInfos[TAG_KEY] =
- AttributeInfo(
- value = when (receiver) {
- is ExpressionReceiver -> receiver.expression
- else -> openTagExpr
- },
- key = null,
- name = TAG_KEY
- )
-
- val result = resolveChild(
- openTagExpr,
- candidates,
- name,
- makeCall(
- callElement = call.callElement,
- calleeExpression = call.calleeExpression,
- receiver = call.explicitReceiver,
- dispatchReceiver = call.dispatchReceiver
- ),
- attrInfos,
- context
- )
-
- tmpTraceAndCache.commit()
- return result
- }
-
- private fun resolveChild(
- expression: KtExpression,
- candidates: Collection<FunctionDescriptor>,
- name: Name,
- call: Call,
- attributes: Map<String, AttributeInfo>,
- context: ExpressionTypingContext
- ): List<ComposableEmitDescriptor> {
- return candidates
- .mapNotNull { result ->
- val tmpForCandidate = TemporaryTraceAndCache.create(
- context, "trace to resolve ktx element", expression
- )
-
- val trace: BindingTrace = tmpForCandidate.trace
-
- val candidateContext = context
- .replaceTraceAndCache(tmpForCandidate)
- .replaceBindingTrace(trace)
-
- val attrsUsedInCall = mutableSetOf<String>()
-
- val attrsUsedInSets = mutableSetOf<String>()
-
- val subMissingRequiredAttributes = mutableListOf<DeclarationDescriptor>()
-
- val usedAttributeInfos = mutableListOf<TempParameterInfo>()
-
- val candidateResults = resolveCandidate(
- result,
- call,
- attributes,
- attrsUsedInCall,
- usedAttributeInfos,
- subMissingRequiredAttributes,
- candidateContext
- )
-
- if (candidateResults.isNothing)
- return@mapNotNull null
-
- val resolvedCall = candidateResults.resultingCalls.first()
-
- if (!candidateResults.isSuccess) {
- when (candidateResults.resultCode) {
- OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH -> {
- resolvedCall.call.valueArguments.map {
- resolvedCall.getArgumentMapping(it)
- }.forEach {
- when (it) {
- is ArgumentMatch -> {
- when (it.status) {
- ArgumentMatchStatus.TYPE_MISMATCH -> {
- return@forEach
- }
- ArgumentMatchStatus.MATCH_MODULO_UNINFERRED_TYPES -> {
- return@forEach
- }
- ArgumentMatchStatus.UNKNOWN -> {
- // NOTE(lmr): This can happen with the implicit constructor params. ignore it
- }
- ArgumentMatchStatus.SUCCESS -> {
- // do nothing
- }
- ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE -> {
- // NOTE(lmr): This can happen when the attribute has no value expression, since
- // we pass in a fake psi node for the value in that case.
- }
- }
- }
- is ArgumentUnmapped -> {
- return@mapNotNull null
- }
- }
- }
- }
- OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE,
- OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES,
- OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER -> {
- return@mapNotNull null
- }
- else -> {
- error("new kind of resolution problem. figure out why this happened...")
- }
- }
- }
-
- if (
- !descriptorsEqualWithSubstitution(
- resolvedCall.semanticCall.candidateDescriptor.original,
- result.original
- )
- ) {
- // if this happens, we've likely resolved the candidate to one of the other candidates, and we don't want that.
- // we fail in this case, since it will succeed once we actually process the candidate that this resolved to.
- return@mapNotNull null
- }
-
- val returnType = resolvedCall.resultingDescriptor.returnType ?: builtIns.unitType
-
- if (!returnType.isEmittable()) return@mapNotNull null
-
- var hasChildren = false
-
- val emitCall = resolveComposerEmit(
- constructedType = returnType,
- hasBody = attributes.contains(CHILDREN_KEY),
- implicitCtorTypes = resolvedCall.call.valueArguments.mapNotNull {
- (it as? ImplicitCtorValueArgument)?.type
- },
- expressionToReportErrorsOn = expression,
- context = candidateContext
- ) ?: return@mapNotNull null
-
- if (attributes.contains(CHILDREN_KEY) && returnType.isCompoundEmittable()) {
- attrsUsedInSets.add(CHILDREN_KEY)
- hasChildren = true
- }
-
- val updateReceiverScope = emitCall
- .resultingDescriptor
- .valueParameters
- .first { it.name == KtxNameConventions.EMIT_UPDATER_PARAMETER }
- .type
- .getReceiverTypeFromFunctionType() ?: error("Expected receiver type")
-
- val setterValidations = resolveAllSetAttributes(
- expressionToReportErrorsOn = expression,
- receiverScope = updateReceiverScope,
- type = returnType,
- attributes = attributes,
- attributesUsedInCall = attrsUsedInCall,
- consumedAttributes = attrsUsedInSets,
- missingRequiredAttributes = subMissingRequiredAttributes,
- context = candidateContext
- )
-
- val pivotals = resolvePivotalAttributes(
- attributes,
- attrsUsedInCall,
- usedAttributeInfos,
- setterValidations,
- returnType
- )
-
- return@mapNotNull ComposableEmitDescriptor.build(
- hasChildren = hasChildren,
- ctorCall = resolvedCall,
- validations = setterValidations,
- pivotals = pivotals,
- ctorParams = resolvedCall.buildParamsFromAttributes(attributes),
- emitCall = emitCall,
- name = name,
- composerMetadata = composer
- )
- }
- }
-
- private fun resolvePivotalAttributes(
- attributes: Map<String, AttributeInfo>,
- attrsUsedInCall: Set<String>,
- callParamInfos: List<TempParameterInfo>,
- validations: List<ValidatedAssignment>,
- returnType: KotlinType?
- ): List<String> {
- val result = mutableListOf<String>()
-
- if (returnType == null || returnType.isUnit()) {
- return emptyList()
- }
-
- val validationSet = validations.map { it.name }.toSet()
-
- // if you were in the ctor call but not in the sets, you *have* to be pivotal
- for (info in callParamInfos) {
- if (validationSet.contains(info.attribute.name)) continue
- attributes[info.attribute.name] ?: continue
- result.add(info.attribute.name)
- }
-
- // There are additional cases where attributes can be pivotal:
- // 1. It is annotated as @Pivotal
- // 2. It is a `val` ctor parameter
- for (assignment in validations) {
- val name = assignment.name
- val descriptor = assignment.descriptor
-
- if (descriptor is PropertyDescriptor &&
- attrsUsedInCall.contains(name) && !descriptor.isVar) {
- result.add(name)
- continue
- }
- }
-
- return result
- }
-
- private fun ResolvedCall<*>.buildParamsFromAttributes(
- attributes: Map<String, AttributeInfo>
- ): List<String> {
- val possbileChildrenParam = valueArguments.keys.possibleChildrenParameter
- return valueArguments.mapNotNull { (param, value) ->
- val name = param.name.asString()
-// var type = param.type
- var attr = attributes[name]
-
- if (param == possbileChildrenParam && attr == null) {
- val childrenAttr = attributes[CHILDREN_KEY]
- if (childrenAttr != null) {
- attr = childrenAttr
- }
-// if (param.isComposableFromChildrenAnnotation()) {
-// type = type.makeComposable(module)
-// }
- }
-
- if (value is DefaultValueArgument) {
- return@mapNotNull null
- }
-
- if (attr == null && isImplicitConstructorParam(param, resultingDescriptor)) {
- return@mapNotNull null
-// ImplicitCtorValueNode(
-// name = name,
-// descriptor = param,
-// type = type
-// )
- }
-
- if (attr == null) {
- error("Couldn't find attribute but expected to. param=$param name=$name")
- }
-
- attr.name
- }
- }
-
- private fun resolveAllSetAttributes(
- expressionToReportErrorsOn: KtExpression,
- receiverScope: KotlinType,
- type: KotlinType?,
- attributes: Map<String, AttributeInfo>,
- attributesUsedInCall: Set<String>,
- consumedAttributes: MutableSet<String>,
- missingRequiredAttributes: MutableList<DeclarationDescriptor>,
- context: ExpressionTypingContext
- ): List<ValidatedAssignment> {
- if (type == null) return emptyList()
- val results = mutableListOf<ValidatedAssignment>()
-
- val tempForAttributes = TemporaryTraceAndCache.create(
- context, "temp for attributes", expressionToReportErrorsOn
- )
-
- val tempForValidations = TemporaryTraceAndCache.create(
- context, "temp for validations", expressionToReportErrorsOn
- )
-
- for ((name, attribute) in attributes) {
- if (name == TAG_KEY) continue
- if (name == CHILDREN_KEY) {
- continue
- }
- val keyExpr = attribute.key ?: error("key expected")
-
- val expectedTypes = mutableListOf<KotlinType>()
-
- var resolvedCall: ResolvedCall<*>? = null
-
- // NOTE(lmr): A ktx element that has access (like it's a recursive call or a nested class) to the private property
- // of the tag will be able to set it as an attribute... I'm not sure if that'a s good thing or not, but unless we
- // do something extra, that is indeed possible. Perhaps it's something we should look into.
-
- if (resolvedCall == null) {
- resolvedCall = resolveAttributeAsSetter(
- type,
- attribute.name,
- keyExpr,
- attribute.value,
- expectedTypes,
- context.replaceTraceAndCache(tempForAttributes)
- )
- }
-
- if (resolvedCall == null) {
- resolvedCall = resolveAttributeAsProperty(
- type,
- keyExpr,
- attribute.value,
- expectedTypes,
- context.replaceTraceAndCache(tempForAttributes)
- )
- }
-
- if (resolvedCall != null) {
-
- val validationType = when {
- attributesUsedInCall.contains(name) -> ValidationType.UPDATE
- else -> ValidationType.SET
- }
-
- val attrType = when (val descriptor = resolvedCall.resultingDescriptor) {
- is FunctionDescriptor -> descriptor.valueParameters.firstOrNull()?.type
- is PropertyDescriptor -> descriptor.type
- else -> null
- } ?: continue
-
- val (validationCall, uncheckedValidationCall, lambdaDescriptor) =
- resolveValidationCall(
- expressionToReportErrorsOn = expressionToReportErrorsOn,
- receiverScope = receiverScope,
- assignmentReceiverScope = type,
- validationType = validationType,
- attrType = attrType,
- context = context.replaceTraceAndCache(tempForValidations)
- )
-
- results.add(
- ValidatedAssignment(
- validationType = validationType,
- assignment = resolvedCall,
- assignmentLambda = lambdaDescriptor,
- name = name,
- validationCall = validationCall,
- uncheckedValidationCall = uncheckedValidationCall,
- descriptor = resolvedCall.resultingDescriptor,
- type = attrType
- )
- )
- consumedAttributes.add(name)
- }
- }
-
- if (!type.isUnit()) {
- val cls = type.constructor.declarationDescriptor as? ClassDescriptor
- ?: error("unexpected classifier descriptor")
- val requiredAttributes = cls.unsubstitutedMemberScope
- .getContributedDescriptors()
- .mapNotNull { it as? PropertyDescriptor }
- // NOTE(lmr): I think we should consider not marking lateinit properties as required. It would maybe align
- // ourselves more with the language semantic of `lateinit`
- .filter {
- it.isLateInit && it.visibility.isVisibleOutside() &&
- !Visibilities.isPrivate(it.visibility)
- }
-
- requiredAttributes
- .filter { !consumedAttributes.contains(it.name.asString()) }
- .ifNotEmpty { missingRequiredAttributes.addAll(this) }
- }
-
- tempForAttributes.commit()
- tempForValidations.commit()
- return results
- }
-
- private fun resolveAttributeAsSetter(
- instanceType: KotlinType,
- name: String,
- keyExpr: KtReferenceExpression,
- valueExpr: KtExpression,
- expectedTypes: MutableCollection<KotlinType>,
- context: ExpressionTypingContext
- ): ResolvedCall<*>? {
- val setterName = Name.identifier(
- ComposeUtils.setterMethodFromPropertyName(
- name
- )
- )
- val receiver = TransientReceiver(instanceType)
-
- val call = makeCall(
- keyExpr,
- calleeExpression = keyExpr,
- valueArguments = listOf(CallMaker.makeValueArgument(valueExpr)),
- receiver = receiver
- )
-
- val temporaryForFunction = TemporaryTraceAndCache.create(
- context, "trace to resolve as function call", keyExpr
- )
-
- val results = callResolver.computeTasksAndResolveCall<FunctionDescriptor>(
- BasicCallResolutionContext.create(
- context.replaceTraceAndCache(temporaryForFunction),
- call,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call)
- ),
- setterName,
- keyExpr,
- NewResolutionOldInference.ResolutionKind.Function
- )
-
- if (results.isNothing) {
- return null
- }
-
- if (results.isAmbiguity || temporaryForFunction.trace.hasTypeMismatchErrorsOn(valueExpr)) {
- expectedTypes.addAll(
- results.resultingCalls.mapNotNull {
- it.resultingDescriptor.valueParameters.firstOrNull()
- }.map { it.type }
- )
- return null
- }
-
- val resolvedCall = OverloadResolutionResultsUtil.getResultingCall(results, context)
- ?: return null
-
- temporaryForFunction.commit()
-
- return resolvedCall
- }
-
- private fun resolveAttributeAsProperty(
- instanceType: KotlinType,
- keyExpr: KtSimpleNameExpression,
- valueExpr: KtExpression,
- expectedTypes: MutableCollection<KotlinType>,
- context: ExpressionTypingContext
- ): ResolvedCall<*>? {
-
- // NOTE(lmr): I'm not sure what the consequences are of using the tagExpr as the receiver...
- val receiver = TransientReceiver(instanceType)
-
- val temporaryForVariable = TemporaryTraceAndCache.create(
- context, "trace to resolve as local variable or property", keyExpr
- )
-
- val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-
- val call = CallMaker.makePropertyCall(receiver, null, keyExpr)
-
- val contextForVariable = BasicCallResolutionContext.create(
- contextToUse,
- call,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS
- )
-
- val results = callResolver.resolveSimpleProperty(contextForVariable)
-
- if (results.isNothing) {
- return null
- }
-
- val resolvedCall = OverloadResolutionResultsUtil.getResultingCall(results, contextToUse)
- ?: return null
-
- val descriptor = resolvedCall.resultingDescriptor as PropertyDescriptor
- val expectedType = descriptor.type
-
- if (temporaryForVariable.trace.hasTypeMismatchErrorsOn(valueExpr)) {
- expectedTypes.add(expectedType)
- return null
- }
-
- if (descriptor.setter == null) {
- // NOTE(lmr): we probably shouldn't do this. if this ends up being a cross-module compile, then the
- // setter will be gone. I'm not sure the right way to figure out whether or not a property is
- // settable or not...
- return null
- }
-
- temporaryForVariable.commit()
-
- return resolvedCall
- }
-
- private fun resolveCandidate(
- candidate: FunctionDescriptor,
- original: Call,
- attributes: Map<String, AttributeInfo>,
- usedAttributes: MutableSet<String>,
- usedAttributeInfos: MutableList<TempParameterInfo>,
- missingRequiredAttributes: MutableList<DeclarationDescriptor>,
- context: ExpressionTypingContext
- ): OverloadResolutionResults<FunctionDescriptor> {
- val valueArguments = mutableListOf<ValueArgument>()
-
- val dispatchReceiver = original.dispatchReceiver
-
- val stableParamNames = candidate.hasStableParameterNames()
-
- val possibleChildrenParameter =
- candidate.valueParameters.possibleChildrenParameter
-
- for (param in candidate.valueParameters) {
- val name = param.name.asString()
- val attr = attributes[name]
- var arg: ValueArgument? = null
-
- if (arg == null && param == possibleChildrenParameter) {
- val childrenAttr = attributes[CHILDREN_KEY]
- if (childrenAttr != null) {
- usedAttributes.add(CHILDREN_KEY)
-
- usedAttributeInfos.add(
- TempParameterInfo(
- attribute = childrenAttr,
- descriptor = param
- )
- )
-
- arg = childrenAttr.toValueArgument(name, stableParamNames)
- }
- }
-
- if (arg == null && attr != null) {
- usedAttributes.add(name)
- usedAttributeInfos.add(
- TempParameterInfo(
- attribute = attr,
- descriptor = param
- )
- )
- context.trace.record(BindingContext.REFERENCE_TARGET, attr.key, param)
- arg = attr.toValueArgument(attr.name, stableParamNames)
- }
-
- if (arg == null && isImplicitConstructorParam(param, candidate)) {
- arg = ImplicitCtorValueArgument(param.type)
- }
-
- if (arg != null) {
- valueArguments.add(arg)
- } else if (!param.declaresDefaultValue()) {
- // missing required parameter!
- if (
- dispatchReceiver?.type?.isExtensionFunctionType != true ||
- param != candidate.valueParameters[0]
- ) {
- // if this isn't the case, the missing parameter is an extension parameter...
- // and it will be provided implicitly. We don't want to diagnose this as a
- // missing attribute. If it is missing, the call resolver will add a
- // diagnostic anyway.
- missingRequiredAttributes.add(param)
- }
- }
- }
-
- val call = makeCall(
- original.callElement,
- valueArguments = valueArguments,
- calleeExpression = original.calleeExpression,
- receiver = original.explicitReceiver,
- dispatchReceiver = dispatchReceiver
- )
-
- val contextForVariable = BasicCallResolutionContext.create(
- context,
- call,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call)
- )
-
- return callResolver.resolveFunctionCall(contextForVariable)
- }
-
- private fun resolveReceiver(
- expression: KtExpression,
- context: ExpressionTypingContext
- ): Receiver? {
- if (expression !is KtQualifiedExpression) return null
- val currentContext = context
- .replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
- .replaceContextDependency(ContextDependency.INDEPENDENT)
-
- expression.elementChain(currentContext)
-
- val receiverExpr = expression.receiverExpression
-
- return context.trace.get(BindingContext.QUALIFIER, receiverExpr)
- ?: ExpressionReceiver.create(
- receiverExpr,
- ErrorUtils.createErrorType("Type for " + receiverExpr.text),
- context.trace.bindingContext
- )
- }
-
- private fun makeValueArgument(
- type: KotlinType,
- context: ExpressionTypingContext,
- forceType: Boolean = false
- ): ValueArgument {
- val fakeExpr = psiFactory.createSimpleName("tmpVar")
-
- context.trace.record(
- BindingContext.EXPRESSION_TYPE_INFO, fakeExpr, KotlinTypeInfo(
- type = type,
- dataFlowInfo = DataFlowInfo.EMPTY,
- jumpOutPossible = false,
- jumpFlowInfo = DataFlowInfo.EMPTY
- )
- )
-
- if (forceType) {
- context.trace.record(BindingContext.PROCESSED, fakeExpr, true)
- }
-
- return CallMaker.makeValueArgument(fakeExpr)
- }
-
- private fun resolveComposerEmit(
- implicitCtorTypes: List<KotlinType>,
- constructedType: KotlinType,
- hasBody: Boolean,
- expressionToReportErrorsOn: KtExpression,
- context: ExpressionTypingContext
- ): ResolvedCall<*>? {
- return resolveSubstitutableComposerMethod(
- KtxNameConventions.EMIT,
- listOfNotNull(
- builtIns.anyType,
- functionType(
- parameterTypes = implicitCtorTypes,
- returnType = constructedType
- ),
- functionType(),
- if (hasBody) functionType() else null
- ),
- constructedType,
- expressionToReportErrorsOn,
- context
- )
- }
-
- private fun resolveSingleValidationCall(
- expressionToReportErrorsOn: KtExpression,
- receiverScope: KotlinType,
- validationType: ValidationType,
- checked: Boolean,
- attrType: KotlinType,
- lambdaArg: ValueArgument?,
- context: ExpressionTypingContext
- ): ResolvedCall<*>? {
- val temporaryForVariable = TemporaryTraceAndCache.create(
- context, "trace to resolve variable", expressionToReportErrorsOn
- )
- val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
- val name = validationType.name.toLowerCase(Locale.ROOT).let {
- if (!checked) (it + "Unchecked") else it
- }
- val calleeExpression = psiFactory.createSimpleName(name)
- val call = makeCall(
- callElement = calleeExpression,
- calleeExpression = calleeExpression,
- valueArguments = listOfNotNull(
- makeValueArgument(attrType, contextToUse, forceType = true),
- lambdaArg
- ),
- receiver = TransientReceiver(receiverScope)
- )
- val results = callResolver.resolveCallWithGivenName(
- BasicCallResolutionContext.create(
- contextToUse,
- call,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(contextToUse.dataFlowInfo, call)
- ),
- call,
- calleeExpression,
- Name.identifier(name)
- )
-
- if (results.isSuccess) return results.resultingCall
-
- if (results.resultCode == OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE) {
-
- // NOTE(lmr): We know the type of the attribute at this point, but it's possible for the validation call to require
- // some help in order to do the type inference for the call. We are just guessing here that the type is going to be
- // the attribute type, and not something more complicated. It is kind of a bummer that we need this and I wonder if
- // there isn't a cleaner way to do this.
-
- for (candidate in results.resultingCalls) {
-
- val typeParam = candidate.typeArguments.keys.singleOrNull() ?: continue
-
- if (!attrType.satisfiesConstraintsOf(typeParam)) continue
-
- val nextTempTrace = TemporaryTraceAndCache.create(
- context, "trace to resolve variable", expressionToReportErrorsOn
- )
-
- val nextContext = context
- .replaceTraceAndCache(nextTempTrace)
- .replaceCollectAllCandidates(false)
-
- val substitutor = TypeSubstitutor.create(
- mapOf(
- typeParam.typeConstructor to attrType.asTypeProjection()
- )
- )
-
- val nextCall = makeCall(
- callElement = expressionToReportErrorsOn,
- calleeExpression = calleeExpression,
- receiver = TransientReceiver(composer.type),
- valueArguments = candidate.candidateDescriptor.valueParameters.map {
- makeValueArgument(it.type, nextContext)
- }
- )
-
- val nextResults = callResolver.resolveCallWithKnownCandidate(
- nextCall,
- TracingStrategyImpl.create(calleeExpression, nextCall),
- BasicCallResolutionContext.create(
- nextContext,
- nextCall,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
- ),
- ResolutionCandidate.create(
- nextCall,
- candidate.candidateDescriptor,
- candidate.dispatchReceiver,
- candidate.explicitReceiverKind,
- substitutor
- ),
- DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
- )
-
- if (nextResults.isSuccess) {
- nextTempTrace.commit()
- return nextResults.resultingCall
- }
- }
- }
-
- return null
- }
-
- private fun resolveValidationCall(
- expressionToReportErrorsOn: KtExpression,
- receiverScope: KotlinType,
- assignmentReceiverScope: KotlinType?,
- validationType: ValidationType,
- attrType: KotlinType,
- context: ExpressionTypingContext
- ): Triple<ResolvedCall<*>?, ResolvedCall<*>?, FunctionDescriptor?> {
- val temporaryForVariable = TemporaryTraceAndCache.create(
- context, "trace to resolve variable", expressionToReportErrorsOn
- )
- val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-
- val includeLambda = validationType != ValidationType.CHANGED
-
- // for call:
- // ValidatorType.set(AttrType, (AttrType) -> Unit): Boolean
- // ValidatorType.update(AttrType, (AttrType) -> Unit): Boolean
- // ValidatorType.changed(AttrType): Boolean
-
- // for emit:
- // ValidatorType.set(AttrType, ElementType.(AttrType) -> Unit): Unit
- // ValidatorType.update(AttrType, ElementType.(AttrType) -> Unit): Unit
- // ValidatorType.changed(AttrType): Unit
-
- val lambdaType = when {
- includeLambda -> functionType(
- parameterTypes = listOf(attrType),
- receiverType = assignmentReceiverScope
- )
- else -> null
- }
- val lambdaArg = lambdaType?.let { makeValueArgument(it, contextToUse) }
- val lambdaDescriptor = lambdaType?.let {
- createFunctionDescriptor(
- it,
- contextToUse
- )
- }
-
- val validationCall = resolveSingleValidationCall(
- expressionToReportErrorsOn = expressionToReportErrorsOn,
- receiverScope = receiverScope,
- validationType = validationType,
- checked = true,
- attrType = attrType,
- lambdaArg = lambdaArg,
- context = context
- )
-
- val uncheckedValidationCall = resolveSingleValidationCall(
- expressionToReportErrorsOn = expressionToReportErrorsOn,
- receiverScope = receiverScope,
- validationType = validationType,
- checked = false,
- attrType = attrType,
- lambdaArg = lambdaArg,
- context = context
- )
-
- return Triple(validationCall, uncheckedValidationCall, lambdaDescriptor)
- }
-
- private fun resolveSubstitutableComposerMethod(
- methodName: Name,
- argumentTypes: List<KotlinType>,
- typeToSubstitute: KotlinType?,
- expressionToReportErrorsOn: KtExpression,
- context: ExpressionTypingContext
- ): ResolvedCall<*>? {
- val temporaryForVariable = TemporaryTraceAndCache.create(
- context, "trace to resolve variable", expressionToReportErrorsOn
- )
- val contextToUse = context.replaceTraceAndCache(temporaryForVariable)
-
- val composerExpr = psiFactory.createSimpleName(methodName.asString())
-
- val call = makeCall(
- callElement = expressionToReportErrorsOn,
- calleeExpression = composerExpr,
- receiver = TransientReceiver(composer.type),
- valueArguments = argumentTypes.map { makeValueArgument(it, contextToUse) }
- )
-
- val results = callResolver.resolveCallWithGivenName(
- BasicCallResolutionContext.create(
- contextToUse,
- call,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(contextToUse.dataFlowInfo, call)
- ),
- call,
- composerExpr,
- methodName
- )
-
- if (results.isSuccess) return results.resultingCall
-
- if (typeToSubstitute == null) return null
-
- val candidates = if (context.collectAllCandidates)
- results.allCandidates ?: emptyList()
- else results.resultingCalls
-
- for (candidate in candidates) {
-
- val typeParam = candidate.candidateDescriptor.typeParameters.singleOrNull() ?: continue
-
- if (!typeToSubstitute.satisfiesConstraintsOf(typeParam)) continue
-
- val nextTempTrace = TemporaryTraceAndCache.create(
- context, "trace to resolve variable", expressionToReportErrorsOn
- )
-
- val nextContext = context
- .replaceTraceAndCache(nextTempTrace)
- .replaceCollectAllCandidates(false)
-
- val substitutor = TypeSubstitutor.create(
- mapOf(
- typeParam.typeConstructor to typeToSubstitute.asTypeProjection()
- )
- )
-
- val nextCall = makeCall(
- callElement = expressionToReportErrorsOn,
- calleeExpression = composerExpr,
- receiver = TransientReceiver(composer.type),
- valueArguments = candidate.candidateDescriptor.valueParameters.map {
- makeValueArgument(it.type, nextContext)
- }
- )
-
- val nextResults = callResolver.resolveCallWithKnownCandidate(
- nextCall,
- TracingStrategyImpl.create(composerExpr, nextCall),
- BasicCallResolutionContext.create(
- nextContext,
- nextCall,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
- ),
- ResolutionCandidate.create(
- nextCall,
- candidate.candidateDescriptor,
- candidate.dispatchReceiver,
- candidate.explicitReceiverKind,
- substitutor
- ),
- DataFlowInfoForArgumentsImpl(nextContext.dataFlowInfo, nextCall)
- )
-
- if (nextResults.isSuccess) {
- nextTempTrace.commit()
- return nextResults.resultingCall
- }
- }
-
- return if (context.collectAllCandidates) null
- else resolveSubstitutableComposerMethod(
- methodName,
- argumentTypes,
- typeToSubstitute,
- expressionToReportErrorsOn,
- context.replaceCollectAllCandidates(true)
- )
- }
-
- private fun KtQualifiedExpression.elementChain(context: ExpressionTypingContext) {
- val moduleDescriptor = context.scope.ownerDescriptor.module
- val trace = context.trace
- val scopeForFirstPart = context.scope
-
- val path = asQualifierPartList()
- val firstPart = path.first()
- var currentDescriptor: DeclarationDescriptor? = scopeForFirstPart.findDescriptor(firstPart)
- currentDescriptor =
- currentDescriptor ?: moduleDescriptor.getPackage(FqName.topLevel(firstPart.name)).let {
- if (it.isEmpty()) null else it
- }
-
- if (currentDescriptor == null) return
- else storeSimpleNameExpression(firstPart.expression!!, currentDescriptor, trace)
-
- // TODO(lmr): we need to add visibility checks into this function...
- for (qualifierPartIndex in 1 until path.size) {
- val qualifierPart = path[qualifierPartIndex]
-
- val nextPackageOrClassDescriptor =
- when (currentDescriptor) {
- // TODO(lmr): i wonder if we could allow this for Ktx. Seems like a nice to have
- // TODO type aliases as qualifiers? (would break some assumptions in TypeResolver)
- is TypeAliasDescriptor -> null
- is ClassDescriptor -> {
- var next: DeclarationDescriptor? = null
- next = next
- ?: currentDescriptor.unsubstitutedInnerClassesScope.findDescriptor(
- qualifierPart
- )
- if (currentDescriptor.kind == ClassKind.OBJECT) {
- next = next
- ?: currentDescriptor.unsubstitutedMemberScope.findDescriptor(
- qualifierPart
- )
- }
- val cod = currentDescriptor.companionObjectDescriptor
- if (cod != null) {
- next = next
- ?: cod.unsubstitutedMemberScope.findDescriptor(qualifierPart)
- }
- next = next ?: currentDescriptor.staticScope.findDescriptor(qualifierPart)
- next
- }
- is PackageViewDescriptor -> {
- val packageView =
- if (qualifierPart.typeArguments == null) {
- moduleDescriptor.getPackage(
- currentDescriptor.fqName.child(qualifierPart.name)
- )
- } else null
- if (packageView != null && !packageView.isEmpty()) {
- packageView
- } else {
- currentDescriptor.memberScope.findDescriptor(qualifierPart)
- }
- }
- is VariableDescriptor -> {
- currentDescriptor.type.memberScope.findDescriptor(qualifierPart)
- }
- else -> null
- }
-
- if (nextPackageOrClassDescriptor == null) return
- else storeSimpleNameExpression(
- qualifierPart.expression!!,
- nextPackageOrClassDescriptor,
- trace
- )
-
- currentDescriptor = nextPackageOrClassDescriptor
- }
- }
-
- private fun storeSimpleNameExpression(
- expression: KtSimpleNameExpression,
- descriptor: DeclarationDescriptor,
- trace: BindingTrace
- ) {
- trace.record(BindingContext.REFERENCE_TARGET, expression, descriptor)
- UnderscoreUsageChecker.checkSimpleNameUsage(descriptor, expression, trace)
-
- val qualifier = when (descriptor) {
- is PackageViewDescriptor -> PackageQualifier(expression, descriptor)
- is ClassDescriptor -> ClassQualifier(expression, descriptor)
- is TypeParameterDescriptor -> TypeParameterQualifier(expression, descriptor)
- is TypeAliasDescriptor -> descriptor.classDescriptor?.let {
- TypeAliasQualifier(expression, descriptor, it)
- }
- else -> null
- }
-
- if (qualifier != null) {
- trace.record(BindingContext.QUALIFIER, qualifier.expression, qualifier)
- }
- }
-}
-
-// general utils
-// ==============================
-
-private val builtIns = DefaultBuiltIns.Instance
-
-private fun functionType(
- parameterTypes: List<KotlinType> = emptyList(),
- annotations: Annotations = Annotations.EMPTY,
- returnType: KotlinType = builtIns.unitType,
- receiverType: KotlinType? = null
-): KotlinType = createFunctionType(
- builtIns = builtIns,
- annotations = annotations,
- parameterNames = null,
- parameterTypes = parameterTypes,
- receiverType = receiverType,
- returnType = returnType
-)
-
-private fun KotlinType.satisfiesConstraintsOf(T: TypeParameterDescriptor): Boolean {
- return T.upperBounds.all { isSubtypeOf(it) }
-}
-
-// We want to return null in cases where types mismatch, so we use this heuristic to find out. I think there might be a more robust
-// way to find this out, but I'm not sure what it would be
-private fun BindingTrace.hasTypeMismatchErrorsOn(element: KtElement): Boolean =
- bindingContext.diagnostics.forElement(element).any { it.severity == Severity.ERROR }
-
-private fun KtExpression.asQualifierPartList(): List<QualifiedExpressionResolver.QualifierPart> {
- val result = SmartList<QualifiedExpressionResolver.QualifierPart>()
-
- fun addQualifierPart(expression: KtExpression?): Boolean {
- if (expression is KtSimpleNameExpression) {
- result.add(
- QualifiedExpressionResolver.ExpressionQualifierPart(
- expression.getReferencedNameAsName(),
- expression
- )
- )
- return true
- }
- return false
- }
-
- var expression: KtExpression? = this
- while (true) {
- if (addQualifierPart(expression)) break
- if (expression !is KtQualifiedExpression) break
-
- addQualifierPart(expression.selectorExpression)
-
- expression = expression.receiverExpression
- }
-
- return result.asReversed()
-}
-
-private fun HierarchicalScope.findDescriptor(
- part: QualifiedExpressionResolver.QualifierPart
-): DeclarationDescriptor? {
- return findFirstFromMeAndParent {
- it.findVariable(part.name, part.location)
- ?: it.findFunction(part.name, part.location)
- ?: it.findClassifier(part.name, part.location)
- }
-}
-
-private fun MemberScope.findDescriptor(
- part: QualifiedExpressionResolver.QualifierPart
-): DeclarationDescriptor? {
- return this.getContributedClassifier(part.name, part.location)
- ?: getContributedFunctions(part.name, part.location).singleOrNull()
- ?: getContributedVariables(part.name, part.location).singleOrNull()
-}
-
-private fun AttributeInfo.toValueArgument(name: String, named: Boolean): ValueArgument {
- val argumentName = if (named) object : ValueArgumentName {
- override val asName: Name
- get() = Name.identifier(name)
- override val referenceExpression: KtSimpleNameExpression?
- get() = key
- } else null
- return object : ValueArgument {
- override fun getArgumentExpression() = value
- override fun getArgumentName() = argumentName
- override fun isNamed() = named
- override fun asElement(): KtElement = value
- override fun getSpreadElement(): LeafPsiElement? = null
- override fun isExternal() = true
- }
-}
-
-/**
- * This function was copied verbatim from descriptorUtils.kt from ide-common. For some reason, importing this method into our module
- * would not work and would cause a NoClassDefFound exception.
- */
-private fun descriptorsEqualWithSubstitution(
- descriptor1: DeclarationDescriptor?,
- descriptor2: DeclarationDescriptor?
-): Boolean {
- if (descriptor1 == descriptor2) return true
- if (descriptor1 == null || descriptor2 == null) return false
- if (descriptor1 !is CallableDescriptor) return true
- descriptor2 as CallableDescriptor
-
- val typeChecker = KotlinTypeCheckerImpl.withAxioms(
- object : KotlinTypeChecker.TypeConstructorEquality {
- override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
- val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor
- val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor
- if (typeParam1 != null && typeParam2 != null &&
- typeParam1.containingDeclaration == descriptor1 &&
- typeParam2.containingDeclaration == descriptor2
- ) {
- return typeParam1.index == typeParam2.index
- }
-
- return a == b
- }
- }
- )
-
- if (!typeChecker.equalTypesOrNulls(descriptor1.returnType, descriptor2.returnType)) return false
-
- val parameters1 = descriptor1.valueParameters
- val parameters2 = descriptor2.valueParameters
- if (parameters1.size != parameters2.size) return false
- for ((param1, param2) in parameters1.zip(parameters2)) {
- if (!typeChecker.equalTypes(param1.type, param2.type)) return false
- }
- // NOTE(lmr): edit
- // this check was added
- if (descriptor1.javaClass !== descriptor2.javaClass) return false
- // NOTE(lmr): /end
- return true
-}
-
-private val ResolvedCall<*>.semanticCall: ResolvedCall<*>
- get() = when (this) {
- is VariableAsFunctionResolvedCall -> variableCall
- else -> this
- }
-
-private val Collection<ValueParameterDescriptor>.possibleChildrenParameter:
- ValueParameterDescriptor?
- get() = maxBy { it.index }?.let { if (it.type.isFunctionType) it else null }
-
-// move these to naming conventions???
-const val CHILDREN_KEY = "<children>"
-const val TAG_KEY = "<tag>"
-
-fun makeCall(
- callElement: KtElement,
- calleeExpression: KtExpression? = null,
- valueArguments: List<ValueArgument> = emptyList(),
- receiver: Receiver? = null,
- dispatchReceiver: ReceiverValue? = null
-): Call {
- return object : Call {
- override fun getDispatchReceiver(): ReceiverValue? = dispatchReceiver
- override fun getValueArgumentList(): KtValueArgumentList? = null
- override fun getTypeArgumentList(): KtTypeArgumentList? = null
- override fun getExplicitReceiver(): Receiver? = receiver
- override fun getCalleeExpression(): KtExpression? = calleeExpression
- override fun getValueArguments(): List<ValueArgument> = valueArguments
- override fun getCallElement(): KtElement = callElement
- override fun getFunctionLiteralArguments(): List<LambdaArgument> = emptyList()
- override fun getTypeArguments(): List<KtTypeProjection> = emptyList()
- override fun getCallType(): Call.CallType = Call.CallType.DEFAULT
- override fun getCallOperationNode(): ASTNode? = null
- }
-}
-
-fun createFunctionDescriptor(
- type: KotlinType,
- context: ExpressionTypingContext
-): FunctionDescriptor {
- return AnonymousFunctionDescriptor(
- context.scope.ownerDescriptor,
- Annotations.EMPTY,
- CallableMemberDescriptor.Kind.SYNTHESIZED,
- SourceElement.NO_SOURCE,
- false
- ).apply {
- initialize(
- type.getReceiverTypeFromFunctionType()?.let {
- DescriptorFactory.createExtensionReceiverParameterForCallable(
- this,
- it,
- Annotations.EMPTY)
- },
- null,
- emptyList(),
- type.getValueParameterTypesFromFunctionType().mapIndexed { i, t ->
- ValueParameterDescriptorImpl(
- containingDeclaration = this,
- original = null,
- index = i,
- annotations = Annotations.EMPTY,
- name = t.type.extractParameterNameFromFunctionTypeArgument()
- ?: Name.identifier("p$i"),
- outType = t.type,
- declaresDefaultValue = false,
- isCrossinline = false,
- isNoinline = false,
- varargElementType = null,
- source = SourceElement.NO_SOURCE
- )
- },
- type.getReturnTypeFromFunctionType(),
- Modality.FINAL,
- Visibilities.LOCAL,
- null
- )
- isOperator = false
- isInfix = false
- isExternal = false
- isInline = false
- isTailrec = false
- isSuspend = false
- isExpect = false
- isActual = false
- }
-}
-
-fun KotlinType.satisfiesConstraintsOf(bounds: List<KotlinType>): Boolean {
- return bounds.all { isSubtypeOf(it) }
-}
-
-fun KotlinType.upperBounds(): List<KotlinType> {
- return if (isTypeParameter()) {
- TypeUtils.getTypeParameterDescriptorOrNull(this)?.upperBounds ?: emptyList()
- } else {
- listOf(this)
- }
-}
-
-// util classes
-// ========================
-class ImplicitCtorValueArgument(val type: KotlinType) : ValueArgument {
- override fun getArgumentExpression(): KtExpression? = null
- override fun getArgumentName(): ValueArgumentName? = null
- override fun isNamed(): Boolean = false
- override fun asElement(): KtElement = error("tried to get element")
- override fun getSpreadElement(): LeafPsiElement? = null
- override fun isExternal(): Boolean = true
-}
-
-class AttributeInfo(
- val value: KtExpression,
- val key: KtSimpleNameExpression?,
- val name: String
-)
-
-class NoInterceptionCallResolver(private val callResolver: CallResolver) {
- fun resolveCallWithGivenName(
- context: ResolutionContext<*>,
- call: Call,
- functionReference: KtReferenceExpression,
- name: Name
- ): OverloadResolutionResults<FunctionDescriptor> {
- context.trace.record(
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- call,
- true
- )
- return callResolver.resolveCallWithGivenName(
- context,
- call,
- functionReference,
- name
- )
- }
-
- fun resolveCallWithKnownCandidate(
- call: Call,
- tracing: TracingStrategy,
- context: ResolutionContext<*>,
- candidate: ResolutionCandidate<FunctionDescriptor>,
- dataFlowInfoForArguments: MutableDataFlowInfoForArguments?
- ): OverloadResolutionResults<FunctionDescriptor> {
- context.trace.record(
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- call,
- true
- )
- return callResolver.resolveCallWithKnownCandidate(
- call,
- tracing,
- context,
- candidate,
- dataFlowInfoForArguments
- )
- }
-
- fun resolveSimpleProperty(
- context: BasicCallResolutionContext
- ): OverloadResolutionResults<VariableDescriptor> {
- return callResolver.resolveSimpleProperty(
- context
- )
- }
-
- fun resolveFunctionCall(
- context: BasicCallResolutionContext
- ): OverloadResolutionResults<FunctionDescriptor> {
- context.trace.record(
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- context.call,
- true
- )
- return callResolver.resolveFunctionCall(
- context
- )
- }
-
- fun <T : CallableDescriptor> computeTasksAndResolveCall(
- context: BasicCallResolutionContext,
- name: Name,
- referenceExpression: KtReferenceExpression,
- kind: NewResolutionOldInference.ResolutionKind
- ): OverloadResolutionResults<T> {
- context.trace.record(
- ComposeWritableSlices.IGNORE_COMPOSABLE_INTERCEPTION,
- context.call,
- true
- )
- return callResolver.computeTasksAndResolveCall(
- context,
- name,
- referenceExpression,
- kind
- )
- }
-}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt
index cf79cb31..856fcc4 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeFqNames.kt
@@ -37,18 +37,17 @@
val Composable = ComposeUtils.composeFqName("Composable")
val CurrentComposerIntrinsic = ComposeUtils.composeFqName("<get-currentComposer>")
val ComposableContract = ComposeUtils.composeFqName("ComposableContract")
- val restartableFunction = FqName.fromSegments(listOf(
+ val composableLambda = FqName.fromSegments(listOf(
"androidx",
"compose",
"internal",
- "restartableFunction"
+ "composableLambda"
))
val remember = ComposeUtils.composeFqName("remember")
val key = ComposeUtils.composeFqName("key")
val StableMarker = ComposeUtils.composeFqName("StableMarker")
val Stable = ComposeUtils.composeFqName("Stable")
val Composer = ComposeUtils.composeFqName("Composer")
- val Untracked = ComposeUtils.composeFqName("Untracked")
val UiComposer = FqName.fromSegments(listOf("androidx", "ui", "node", "UiComposer"))
val Package = FqName.fromSegments(listOf("androidx", "compose"))
val Function0 = FqName.fromSegments(listOf("kotlin", "jvm", "functions", "Function0"))
@@ -87,8 +86,10 @@
val contract = annotations.findAnnotation(ComposeFqNames.ComposableContract) ?: return null
return contract.argumentValue("readonly")?.value as? Boolean
}
-fun Annotated.hasUntrackedAnnotation(): Boolean =
- annotations.findAnnotation(ComposeFqNames.Untracked) != null
+fun Annotated.composableTrackedContract(): Boolean? {
+ val contract = annotations.findAnnotation(ComposeFqNames.ComposableContract) ?: return null
+ return contract.argumentValue("tracked")?.value as? Boolean
+}
internal val KotlinType.isSpecialType: Boolean get() =
this === NO_EXPECTED_TYPE || this === UNIT_EXPECTED_TYPE
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt
index 0a8b850..741e114 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt
@@ -16,12 +16,10 @@
package androidx.compose.plugins.kotlin
-import androidx.compose.plugins.kotlin.compiler.lower.ComposableCallTransformer
import androidx.compose.plugins.kotlin.compiler.lower.ComposerIntrinsicTransformer
import androidx.compose.plugins.kotlin.compiler.lower.ComposerLambdaMemoization
import androidx.compose.plugins.kotlin.compiler.lower.ComposerParamTransformer
import androidx.compose.plugins.kotlin.compiler.lower.ComposableFunctionBodyTransformer
-import androidx.compose.plugins.kotlin.compiler.lower.ComposeResolutionMetadataTransformer
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -43,10 +41,6 @@
// create a symbol remapper to be used across all transforms
val symbolRemapper = DeepCopySymbolRemapper()
- // add metadata from the frontend onto IR Nodes so that the metadata will travel
- // with the ir nodes as they transform and get copied
- ComposeResolutionMetadataTransformer(pluginContext).lower(moduleFragment)
-
// Memoize normal lambdas and wrap composable lambdas
ComposerLambdaMemoization(pluginContext, symbolRemapper, bindingTrace).lower(moduleFragment)
@@ -72,12 +66,6 @@
).lower(moduleFragment)
generateSymbols(pluginContext)
-
- // transform composable calls and emits into their corresponding calls appealing
- // to the composer
- ComposableCallTransformer(pluginContext, symbolRemapper, bindingTrace).lower(moduleFragment)
-
- generateSymbols(pluginContext)
}
}
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt
index 736511e..7e3e8b7 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeUtils.kt
@@ -16,19 +16,7 @@
package androidx.compose.plugins.kotlin
-import org.jetbrains.kotlin.descriptors.ClassDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
-import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.psi.KtCallExpression
-import org.jetbrains.kotlin.psi.KtFunction
-import org.jetbrains.kotlin.psi.KtFunctionLiteral
-import org.jetbrains.kotlin.psi.KtLambdaArgument
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
-import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
object ComposeUtils {
@@ -39,39 +27,4 @@
fun composeInternalFqName(cname: String? = null) = FqName(
"${generateComposePackageName()}.internal${cname?.let { ".$it"} ?: ""}"
)
-
- fun setterMethodFromPropertyName(name: String): String {
- return "set${name[0].toUpperCase()}${name.slice(1 until name.length)}"
- }
-
- fun propertyNameFromSetterMethod(name: String): String {
- return if (name.startsWith("set")) "${
- name[3].toLowerCase()
- }${name.slice(4 until name.length)}" else name
- }
-
- fun isSetterMethodName(name: String): Boolean {
- // use !lower to capture non-alpha chars
- return name.startsWith("set") && name.length > 3 && !name[3].isLowerCase()
- }
-
- fun isComposeComponent(descriptor: DeclarationDescriptor): Boolean {
- if (descriptor !is ClassDescriptor) return false
- val baseComponentDescriptor =
- descriptor.module.findClassAcrossModuleDependencies(
- ClassId.topLevel(
- FqName(ComposeUtils.generateComposePackageName() + ".Component")
- )
- ) ?: return false
- return descriptor.isSubclassOf(baseComponentDescriptor)
- }
-}
-
-fun KtFunction.isEmitInline(bindingContext: BindingContext): Boolean {
- if (this !is KtFunctionLiteral) return false
- if (parent?.parent !is KtLambdaArgument) return false
- val call = parent?.parent?.parent as? KtCallExpression
- val resolvedCall = call?.getResolvedCall(bindingContext)
- return resolvedCall != null &&
- resolvedCall.candidateDescriptor is ComposableEmitDescriptor
}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposerMetadata.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposerMetadata.kt
deleted file mode 100644
index 9842f72..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposerMetadata.kt
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.plugins.kotlin
-
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
-import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
-import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi.KtPsiFactory
-import org.jetbrains.kotlin.resolve.calls.CallResolver
-import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
-import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
-import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
-import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.isError
-import org.jetbrains.kotlin.types.typeUtil.isNothingOrNullableNothing
-import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
-
-class ComposerMetadata(
- val type: KotlinType,
- // Set of valid upper bound types that were defined on the composer that can't have children
- // For android, this should be [View]
- private val emitSimpleUpperBoundTypes: Set<KotlinType>,
- // Set of valid upper bound types that were defined on the composer that can have children.
- // For android, this would be [ViewGroup]
- private val emitCompoundUpperBoundTypes: Set<KotlinType>,
- // The specification for `emit` on a composer allows for the `ctor` parameter to be a function type
- // with any number of parameters. We allow for these parameters to be used as parameters in the
- // Constructors that are emitted with a KTX tag. These parameters can be overridden with attributes
- // in the KTX tag, but if there are required parameters with a type that matches one declared in the
- // ctor parameter, we will resolve it automatically with the value passed in the `ctor` lambda.
- //
- // In order to do this resolution, we store a list of pairs of "upper bounds" to parameter types. For example,
- // the following emit call:
- //
- // fun <T : View> emit(key: Any, ctor: (context: Context) -> T, update: U<T>.() -> Unit)
- //
- // would produce a Pair of [View] to [Context]
- private val emittableTypeToImplicitCtorTypes: List<Pair<List<KotlinType>, Set<KotlinType>>>
-) {
-
- companion object {
- private fun resolveComposerMethodCandidates(
- name: Name,
- context: BasicCallResolutionContext,
- composerType: KotlinType,
- callResolver: CallResolver,
- psiFactory: KtPsiFactory
- ): Collection<ResolvedCall<*>> {
- val calleeExpression = psiFactory.createSimpleName(name.asString())
-
- val methodCall = makeCall(
- callElement = context.call.callElement,
- calleeExpression = calleeExpression,
- receiver = TransientReceiver(
- composerType
- )
- )
-
- val contextForVariable =
- BasicCallResolutionContext.create(
- context,
- methodCall,
- CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
- DataFlowInfoForArgumentsImpl(
- context.dataFlowInfo,
- methodCall
- )
- )
-
- val results = callResolver.resolveCallWithGivenName(
- // it's important that we use "collectAllCandidates" so that extension functions get included
- contextForVariable.replaceCollectAllCandidates(true),
- methodCall,
- calleeExpression,
- name
- )
-
- return results.allCandidates ?: emptyList()
- }
-
- fun build(
- composerType: KotlinType,
- callResolver: CallResolver,
- psiFactory: KtPsiFactory,
- resolutionContext: BasicCallResolutionContext
- ): ComposerMetadata {
- val emitSimpleUpperBoundTypes = mutableSetOf<KotlinType>()
- val emitCompoundUpperBoundTypes = mutableSetOf<KotlinType>()
- val emittableTypeToImplicitCtorTypes =
- mutableListOf<Pair<List<KotlinType>, Set<KotlinType>>>()
-
- val emitCandidates = resolveComposerMethodCandidates(
- KtxNameConventions.EMIT,
- resolutionContext,
- composerType,
- callResolver,
- psiFactory
- )
-
- for (candidate in emitCandidates.map { it.candidateDescriptor }) {
- if (candidate.name != KtxNameConventions.EMIT) continue
- if (candidate !is SimpleFunctionDescriptor) continue
- val params = candidate.valueParameters
- // NOTE(lmr): we could report diagnostics on some of these? it seems strange to emit diagnostics about a function
- // that is not necessarily being used though. I think it's probably better to just ignore them here.
-
- // the signature of emit that we are looking for has 3 or 4 parameters
- if (params.size < 3 || params.size > 4) continue
- val ctorParam = params.find {
- it.name == KtxNameConventions.EMIT_CTOR_PARAMETER
- } ?: continue
- if (!ctorParam.type.isFunctionTypeOrSubtype) continue
-
- // the return type from the ctor param is the "upper bound" of the node type. It will often be a generic type with constraints.
- val upperBounds = ctorParam.type.getReturnTypeFromFunctionType().upperBounds()
-
- // the ctor param can have parameters itself, which we interpret as implicit parameter types that the composer knows how to
- // automatically provide to the component. In the case of Android Views, this is how we automatically provide Context.
- val implicitParamTypes =
- ctorParam.type.getValueParameterTypesFromFunctionType().map {
- it.type
- }
-
- for (implicitType in implicitParamTypes) {
- emittableTypeToImplicitCtorTypes.add(upperBounds to implicitParamTypes.toSet())
- }
-
- emitSimpleUpperBoundTypes.addAll(upperBounds)
-
- if (params.any { it.name == KtxNameConventions.EMIT_CHILDREN_PARAMETER }) {
- emitCompoundUpperBoundTypes.addAll(upperBounds)
- }
- }
-
- return ComposerMetadata(
- composerType,
- emitSimpleUpperBoundTypes,
- emitCompoundUpperBoundTypes,
- emittableTypeToImplicitCtorTypes
- )
- }
-
- fun getOrBuild(
- composerType: KotlinType,
- callResolver: CallResolver,
- psiFactory: KtPsiFactory,
- resolutionContext: BasicCallResolutionContext
- ): ComposerMetadata {
- val meta = resolutionContext.trace.bindingContext[
- ComposeWritableSlices.COMPOSER_METADATA,
- composerType
- ]
- return if (meta == null) {
- val built = build(composerType, callResolver, psiFactory, resolutionContext)
- resolutionContext.trace.record(
- ComposeWritableSlices.COMPOSER_METADATA,
- composerType,
- built
- )
- built
- } else {
- meta
- }
- }
- }
-
- fun isEmittable(type: KotlinType) =
- !type.isError && !type.isNothingOrNullableNothing() && emitSimpleUpperBoundTypes.any {
- type.isSubtypeOf(it)
- }
-
- fun isCompoundEmittable(type: KotlinType) = !type.isError &&
- !type.isNothingOrNullableNothing() &&
- emitCompoundUpperBoundTypes.any {
- type.isSubtypeOf(it)
- }
-
- fun isImplicitConstructorParam(
- param: ValueParameterDescriptor,
- fn: CallableDescriptor
- ): Boolean {
- val returnType = fn.returnType ?: return false
- val paramType = param.type
- for ((upperBounds, implicitTypes) in emittableTypeToImplicitCtorTypes) {
- if (!implicitTypes.any { it.isSubtypeOf(paramType) }) continue
- if (!returnType.satisfiesConstraintsOf(upperBounds)) continue
- return true
- }
- return false
- }
-}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt
index ffb71c6..b306a6f 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/KtxNameConventions.kt
@@ -8,19 +8,8 @@
val KEY_PARAMETER = Name.identifier("\$key")
val CHANGED_PARAMETER = Name.identifier("\$changed")
val DEFAULT_PARAMETER = Name.identifier("\$default")
- val EMIT = Name.identifier("emit")
val JOINKEY = Name.identifier("joinKey")
val STARTRESTARTGROUP = Name.identifier("startRestartGroup")
val ENDRESTARTGROUP = Name.identifier("endRestartGroup")
val UPDATE_SCOPE = Name.identifier("updateScope")
-
- val EMIT_KEY_PARAMETER = Name.identifier("key")
- val EMIT_CTOR_PARAMETER = Name.identifier("ctor")
- val EMIT_UPDATER_PARAMETER = Name.identifier("update")
- val EMIT_CHILDREN_PARAMETER = Name.identifier("children")
-
- val CALL_KEY_PARAMETER = Name.identifier("key")
- val CALL_CTOR_PARAMETER = Name.identifier("ctor")
- val CALL_INVALID_PARAMETER = Name.identifier("invalid")
- val CALL_BLOCK_PARAMETER = Name.identifier("block")
}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt
index 20e9f8e..ca4d395 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeDefaultErrorMessages.kt
@@ -2,46 +2,22 @@
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
-import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer
-import org.jetbrains.kotlin.diagnostics.rendering.Renderers
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_COLLECTION_OF_TYPES
-import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
object ComposeDefaultErrorMessages : DefaultErrorMessages.Extension {
private val MAP = DiagnosticFactoryToRendererMap("Compose")
override fun getMap() = MAP
- val OUR_STRING_RENDERER = object : DiagnosticParameterRenderer<String> {
- override fun render(obj: String, renderingContext: RenderingContext): String {
- return obj
- }
- }
-
init {
MAP.put(
- ComposeErrors.NO_COMPOSER_FOUND,
- "Couldn't find a valid composer."
- )
- MAP.put(
ComposeErrors.OPEN_MODEL,
"Model objects cannot be open or abstract"
)
MAP.put(
- ComposeErrors.INVALID_COMPOSER_IMPLEMENTATION,
- "Composer of type ''{0}'' was found to be an invalid Composer implementation. " +
- "Reason: {1}",
- Renderers.RENDER_TYPE,
- OUR_STRING_RENDERER
- )
- MAP.put(
ComposeErrors.SUSPEND_FUNCTION_USED_AS_SFC,
"Suspend functions are not allowed to be used as Components"
)
MAP.put(
- ComposeErrors.INVALID_TYPE_SIGNATURE_SFC,
- "Only Unit-returning functions are allowed to be used as Components"
- )
- MAP.put(
ComposeErrors.COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE,
"Functions which invoke @Composable functions must be marked with the @Composable " +
"annotation"
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java
index c4c4d9f..b7ab4aa7 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeErrors.java
@@ -37,12 +37,6 @@
SUSPEND_FUNCTION_USED_AS_SFC = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement>
COMPOSABLE_INVOCATION_IN_NON_COMPOSABLE = DiagnosticFactory0.create(ERROR);
- DiagnosticFactory0<KtElement>
- INVALID_TYPE_SIGNATURE_SFC = DiagnosticFactory0.create(ERROR);
- DiagnosticFactory0<KtElement>
- NO_COMPOSER_FOUND = DiagnosticFactory0.create(ERROR);
- DiagnosticFactory2<KtElement, KotlinType, String>
- INVALID_COMPOSER_IMPLEMENTATION = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<KtExpression, Collection<KotlinType>, Collection<KotlinType>>
ILLEGAL_ASSIGN_TO_UNIONTYPE = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<PsiElement>
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt
index 7fdfad4..b0edb3e 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/analysis/ComposeWritableSlices.kt
@@ -1,12 +1,9 @@
package androidx.compose.plugins.kotlin.analysis
import androidx.compose.plugins.kotlin.ComposableAnnotationChecker
-import androidx.compose.plugins.kotlin.ComposableEmitMetadata
-import androidx.compose.plugins.kotlin.ComposerMetadata
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
-import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice
import org.jetbrains.kotlin.util.slicedMap.RewritePolicy
@@ -22,16 +19,8 @@
BasicWritableSlice(RewritePolicy.DO_NOTHING)
val STABLE_TYPE: WritableSlice<KotlinType, Boolean?> =
BasicWritableSlice(RewritePolicy.DO_NOTHING)
- val COMPOSER_METADATA: WritableSlice<KotlinType, ComposerMetadata> =
- BasicWritableSlice(RewritePolicy.DO_NOTHING)
- val IGNORE_COMPOSABLE_INTERCEPTION: WritableSlice<Call, Boolean> =
- BasicWritableSlice(RewritePolicy.DO_NOTHING)
- val COMPOSABLE_EMIT_METADATA: WritableSlice<IrAttributeContainer, ComposableEmitMetadata> =
- BasicWritableSlice(RewritePolicy.DO_NOTHING)
val IS_COMPOSABLE_CALL: WritableSlice<IrAttributeContainer, Boolean> =
BasicWritableSlice(RewritePolicy.DO_NOTHING)
- val IS_INLINE_COMPOSABLE_CALL: WritableSlice<IrAttributeContainer, Boolean> =
- BasicWritableSlice(RewritePolicy.DO_NOTHING)
val IS_SYNTHETIC_COMPOSABLE_CALL: WritableSlice<IrFunctionAccessExpression, Boolean> =
BasicWritableSlice(RewritePolicy.DO_NOTHING)
}
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt
index 055d52e..e8384da 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt
@@ -21,7 +21,6 @@
import androidx.compose.plugins.kotlin.KtxNameConventions
import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
import androidx.compose.plugins.kotlin.isMarkedStable
import androidx.compose.plugins.kotlin.isSpecialType
import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
@@ -304,9 +303,6 @@
)
)
return true
- if (it.isEmitInline(context.bindingContext)) {
- return true
- }
}
}
return false
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt
deleted file mode 100644
index 1f94017..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt
+++ /dev/null
@@ -1,443 +0,0 @@
-package androidx.compose.plugins.kotlin.compiler.lower
-
-import androidx.compose.plugins.kotlin.ComposableEmitMetadata
-import androidx.compose.plugins.kotlin.EmitChildrenValueParameterDescriptor
-import androidx.compose.plugins.kotlin.KtxNameConventions
-import androidx.compose.plugins.kotlin.ValidatedAssignment
-import androidx.compose.plugins.kotlin.ValidationType
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.irTrace
-import org.jetbrains.kotlin.backend.common.FileLoweringPass
-import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
-import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
-import org.jetbrains.kotlin.backend.common.pop
-import org.jetbrains.kotlin.backend.common.push
-import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
-import org.jetbrains.kotlin.ir.IrStatement
-import org.jetbrains.kotlin.ir.builders.IrBlockBuilder
-import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
-import org.jetbrains.kotlin.ir.builders.irBlock
-import org.jetbrains.kotlin.ir.builders.irCall
-import org.jetbrains.kotlin.ir.builders.irGet
-import org.jetbrains.kotlin.ir.builders.irInt
-import org.jetbrains.kotlin.ir.builders.irReturn
-import org.jetbrains.kotlin.ir.builders.irReturnUnit
-import org.jetbrains.kotlin.ir.builders.irTemporary
-import org.jetbrains.kotlin.ir.declarations.IrDeclaration
-import org.jetbrains.kotlin.ir.declarations.IrFile
-import org.jetbrains.kotlin.ir.declarations.IrFunction
-import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
-import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
-import org.jetbrains.kotlin.ir.declarations.IrValueParameter
-import org.jetbrains.kotlin.ir.declarations.getIrValueParameter
-import org.jetbrains.kotlin.ir.expressions.IrCall
-import org.jetbrains.kotlin.ir.expressions.IrConst
-import org.jetbrains.kotlin.ir.expressions.IrExpression
-import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
-import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
-import org.jetbrains.kotlin.ir.expressions.getValueArgument
-import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
-import org.jetbrains.kotlin.ir.expressions.putTypeArguments
-import org.jetbrains.kotlin.ir.expressions.putValueArgument
-import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
-import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi2ir.findFirstFunction
-import org.jetbrains.kotlin.resolve.BindingTrace
-import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
-import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
-
-class ComposableCallTransformer(
- context: IrPluginContext,
- symbolRemapper: DeepCopySymbolRemapper,
- bindingTrace: BindingTrace
-) :
- AbstractComposeLowering(context, symbolRemapper, bindingTrace),
- FileLoweringPass,
- ModuleLoweringPass {
-
- override fun lower(module: IrModuleFragment) {
- module.transformChildrenVoid(this)
- }
-
- override fun lower(irFile: IrFile) {
- irFile.transformChildrenVoid(this)
- }
-
- private val declarationStack = mutableListOf<IrSymbolOwner>()
-
- override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
- if (declaration !is IrSymbolOwner) return super.visitDeclaration(declaration)
- try {
- declarationStack.push(declaration)
- return super.visitDeclaration(declaration)
- } finally {
- declarationStack.pop()
- }
- }
-
- override fun visitCall(expression: IrCall): IrExpression {
- val emitMetadata = context.irTrace[
- ComposeWritableSlices.COMPOSABLE_EMIT_METADATA,
- expression
- ]
- if (emitMetadata != null) {
- return DeclarationIrBuilder(context, declarationStack.last().symbol).irBlock {
- +irComposableEmit(expression.transformChildren(), emitMetadata)
- }
- }
- return super.visitCall(expression)
- }
-
- override fun visitFunctionExpression(expression: IrFunctionExpression): IrExpression {
- if (expression.origin == IrStatementOrigin.LAMBDA) {
- if (expression.function.valueParameters.lastOrNull()?.isComposerParam() == true) {
- return DeclarationIrBuilder(context, declarationStack.last().symbol).irBlock {
- +expression.transformChildren()
- }
- }
- }
- return super.visitFunctionExpression(expression)
- }
-
- private fun isChildrenParameter(desc: ValueParameterDescriptor, expr: IrExpression): Boolean {
- return expr is IrFunctionExpression &&
- expr.origin == IrStatementOrigin.LAMBDA &&
- desc is EmitChildrenValueParameterDescriptor
- }
-
- private fun IrBlockBuilder.getParameterExpression(
- desc: ValueParameterDescriptor,
- expr: IrExpression?
- ): () -> IrExpression? {
- if (expr == null)
- return { null }
- return when {
- expr is IrConst<*> ->
- ({ expr.copy() })
- isChildrenParameter(desc, expr) ->
- ({ expr })
- else -> {
- val temp = irTemporary(
- value = expr,
- irType = expr.type
- )
- ({ irGet(temp) })
- }
- }
- }
-
- private fun nearestComposer(): IrValueParameter {
- for (fn in declarationStack.asReversed()) {
- if (fn is IrFunction) {
- val param = fn.composerParam()
- if (param != null) {
- return param
- }
- }
- }
- error("Couldn't find composer parameter")
- }
-
- private fun IrBlockBuilder.irComposableEmit(
- original: IrCall,
- emitMetadata: ComposableEmitMetadata
- ): IrExpression {
- val composerParam = nearestComposer()
- return irComposableEmitBase(
- original,
- { irGet(composerParam) },
- emitMetadata
- )
- }
-
- private fun IrBlockBuilder.irComposableEmitBase(
- original: IrCall,
- getComposer: () -> IrExpression,
- emitMetadata: ComposableEmitMetadata
- ): IrExpression {
- /*
-
- TextView(text="foo")
-
- // transforms into
-
- val attr_text = "foo"
- composer.emit(
- key = 123,
- ctor = { context -> TextView(context) },
- update = { set(attr_text) { text -> this.text = text } }
- )
- */
- val parametersByName = original
- .symbol
- .descriptor
- .valueParameters
- .mapNotNull { desc ->
- original.getValueArgument(desc)?.let { desc to it }
- }
- .map { (desc, expr) ->
- desc.name.asString() to getParameterExpression(desc, expr)
- }
- .toMap()
-
- val emitCall = emitMetadata.emitCall
- val emitFunctionDescriptor = emitCall.candidateDescriptor
-
- val emitParameters = emitFunctionDescriptor.valueParameters
- .map { it.name to it }
- .toMap()
-
- fun getEmitParameter(name: Name) = emitParameters[name]
- ?: error("Expected $name parameter to exist")
-
- val emitFunctionSymbol = referenceFunction(emitFunctionDescriptor)
-
- val joinKeyDescriptor = composerTypeDescriptor
- .unsubstitutedMemberScope
- .findFirstFunction(KtxNameConventions.JOINKEY.identifier) {
- it.valueParameters.size == 2
- }
-
- fun irGetParameter(name: String): IrExpression = parametersByName[name]?.invoke()
- ?: error("No parameter found with name $name")
-
- return irCall(
- callee = emitFunctionSymbol,
- type = builtIns.unitType
- ).apply {
- dispatchReceiver = getComposer()
- // TODO(lmr): extensionReceiver.
- // We would want to do this to enable "emit" and "call" implementations that are
- // extensions on the composer
-
- putTypeArguments(emitCall.typeArguments) { it.toIrType() }
-
- putValueArgument(
- getEmitParameter(KtxNameConventions.EMIT_KEY_PARAMETER),
- irGroupKey(
- original = original,
- getComposer = getComposer,
- joinKey = joinKeyDescriptor,
- pivotals = emitMetadata.pivotals.map { irGetParameter(it) }
- )
- )
-
- val ctorParam = getEmitParameter(KtxNameConventions.EMIT_CTOR_PARAMETER)
-
- val ctorLambdaDescriptor = createFunctionDescriptor(ctorParam.type)
-
- putValueArgument(
- ctorParam,
- irLambdaExpression(
- original.startOffset,
- original.endOffset,
- descriptor = ctorLambdaDescriptor,
- type = ctorParam.type.toIrType()
- ) { fn ->
-
- val ctorCall = emitMetadata.ctorCall
-
- val ctorCallSymbol = referenceConstructor(
- ctorCall.candidateDescriptor as ClassConstructorDescriptor
- )
-
- +irReturn(IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset,
- ctorCall.candidateDescriptor.returnType!!.toIrType(), ctorCallSymbol)
- .apply {
- putTypeArguments(ctorCall.typeArguments) { it.toIrType() }
- ctorLambdaDescriptor.valueParameters.zip(
- ctorCall
- .candidateDescriptor!!
- .valueParameters
- ) { a, b ->
- putValueArgument(
- b,
- irGet(fn.getIrValueParameter(a))
- )
- }
- emitMetadata.ctorParams.forEach { name ->
- val param = ctorCall
- .candidateDescriptor
- .valueParameters
- .firstOrNull { it.name.identifier == name }
- if (param != null) {
- putValueArgument(
- param,
- irGetParameter(name)
- )
- }
- }
- })
- }
- )
-
- val updateParam = getEmitParameter(
- KtxNameConventions
- .EMIT_UPDATER_PARAMETER
- )
-
- val updateLambdaDescriptor = createFunctionDescriptor(updateParam.type)
-
- putValueArgument(
- updateParam,
- irLambdaExpression(
- original.startOffset,
- original.endOffset,
- descriptor = updateLambdaDescriptor,
- type = updateParam.type.toIrType()
- ) { fn ->
- emitMetadata.validations.forEach {
- // set(attr_text) { text -> this.text = text }
- val arg = irGetParameter(it.name)
- +irValidatedAssignment(
- arg.startOffset,
- arg.endOffset,
- memoizing = true,
- validation = it,
- receiver = irGet(fn.extensionReceiverParameter!!),
- attributeValue = arg
- )
- }
- +irReturnUnit()
- }
- )
-
- if (emitMetadata.hasChildren) {
- val bodyParam = getEmitParameter(KtxNameConventions.EMIT_CHILDREN_PARAMETER)
-
- val childrenExpr = irGetParameter("\$CHILDREN")
-
- putValueArgument(
- bodyParam,
- childrenExpr
- )
- }
- }
- }
-
- private fun IrBuilderWithScope.irGroupKey(
- original: IrCall,
- joinKey: FunctionDescriptor,
- getComposer: () -> IrExpression,
- pivotals: List<IrExpression>
- ): IrExpression {
- val keyValueExpression = irInt(original.sourceLocationHash())
- return if (pivotals.isEmpty()) keyValueExpression
- else (listOf(keyValueExpression) + pivotals).reduce { accumulator, value ->
- irCall(
- callee = referenceFunction(joinKey),
- type = joinKey.returnType!!.toIrType()
- ).apply {
- dispatchReceiver = getComposer()
- putValueArgument(0, accumulator)
- putValueArgument(1, value)
- }
- }
- }
-
- private fun IrCall.sourceLocationHash(): Int {
- return symbol.descriptor.fqNameSafe.toString().hashCode() xor startOffset
- }
-
- private fun IrBuilderWithScope.irValidatedAssignment(
- startOffset: Int,
- endOffset: Int,
- memoizing: Boolean,
- validation: ValidatedAssignment,
- receiver: IrExpression,
- attributeValue: IrExpression
- ): IrExpression {
- // for emit, fnDescriptor is Validator.(Value) -> Unit or Validator.(Value, Element.(Value) -> Unit) -> Unit
- // for call, fnDescriptor is Validator.(Value) -> Boolean or Validator.(Value, (Value) -> Unit) -> Boolean
-
- // in emit, the element is passed through an extension parameter
- // in call, the element is passed through a capture scope
- val validationCall =
- if (memoizing) validation.validationCall
- else validation.uncheckedValidationCall
-
- if (validationCall == null) error("Expected validationCall to be non-null")
-
- val validationCallDescriptor = validationCall.candidateDescriptor as FunctionDescriptor
-
- return irCall(
- callee = referenceFunction(validationCallDescriptor),
- type = validationCallDescriptor.returnType?.toIrType()!!
- ).apply {
-
- dispatchReceiver = receiver
- // TODO(lmr): extensionReceiver.
- // This might be something we want to be able to do in the cases where we want to
- // build extension `changed(...)` or `set(..) { ... }` methods
-
- putTypeArguments(validationCall.typeArguments) { it.toIrType() }
-
- putValueArgument(0, attributeValue)
- val assignment = validation.assignment
- if (assignment != null && validation.validationType != ValidationType.CHANGED) {
- val assignmentLambdaDescriptor = validation.assignmentLambda
- ?: error("Expected assignmentLambda to be non-null")
- val assignmentDescriptor = assignment.candidateDescriptor.original
-
- val assignmentSymbol = when (assignmentDescriptor) {
- is PropertyDescriptor -> referenceFunction(
- assignmentDescriptor.setter!!
- )
- else -> referenceFunction(assignmentDescriptor)
- }
- val assignmentValueParameterDescriptor = assignmentLambdaDescriptor
- .valueParameters[0]
-
- putValueArgument(
- 1,
- irLambdaExpression(
- startOffset,
- endOffset,
- assignmentLambdaDescriptor,
- validationCallDescriptor.valueParameters[1].type.toIrType()
- ) { fn ->
- +irReturn(
- irCall(
- callee = assignmentSymbol,
- type = builtIns.unitType
- ).apply {
- putTypeArguments(assignment.typeArguments) { it.toIrType() }
- when (assignment.explicitReceiverKind) {
- ExplicitReceiverKind.DISPATCH_RECEIVER -> {
- dispatchReceiver = irGet(fn.extensionReceiverParameter!!)
- }
- ExplicitReceiverKind.EXTENSION_RECEIVER -> {
- extensionReceiver = irGet(fn.extensionReceiverParameter!!)
- }
- ExplicitReceiverKind.BOTH_RECEIVERS -> {
- // NOTE(lmr): This should not be possible. This would have
- // to be an extension method on the ComposerUpdater class
- // itself for the emittable type.
- error(
- "Extension instance methods are not allowed for " +
- "assignments"
- )
- }
- ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> {
- // NOTE(lmr): This is not possible
- error("Static methods are invalid for assignments")
- }
- }
- putValueArgument(
- 0,
- irGet(
- fn.getIrValueParameter(assignmentValueParameterDescriptor)
- )
- )
- }
- )
- }
- )
- }
- }
- }
-}
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt
index b2b9ca7..ef37fa3 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableFunctionBodyTransformer.kt
@@ -18,12 +18,9 @@
import androidx.compose.plugins.kotlin.ComposeFqNames
import androidx.compose.plugins.kotlin.KtxNameConventions
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
import androidx.compose.plugins.kotlin.composableReadonlyContract
import androidx.compose.plugins.kotlin.composableRestartableContract
-import androidx.compose.plugins.kotlin.hasUntrackedAnnotation
-import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
+import androidx.compose.plugins.kotlin.composableTrackedContract
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
@@ -270,6 +267,7 @@
interface IrChangedBitMaskVariable : IrChangedBitMaskValue {
fun asStatements(): List<IrStatement>
fun irOrSetBitsAtSlot(slot: Int, value: IrExpression): IrExpression
+ fun irSetSlotUncertain(slot: Int): IrExpression
}
/**
@@ -600,9 +598,9 @@
if (!scope.isComposable) return super.visitFunction(declaration)
val restartable = declaration.shouldBeRestartable()
val isLambda = declaration.isLambda()
- // if the lambda is untracked, we generate the body like a non-restartable function since
- // the group/update scope is not going to be handled by the RestartableFunction class
- val isTracked = !declaration.descriptor.hasUntrackedAnnotation()
+
+ // we use != false because a null value is treated as "tracked"
+ val isTracked = declaration.descriptor.composableTrackedContract() != false
if (declaration.body == null) return declaration
@@ -635,7 +633,7 @@
// Currently, we make all composable functions restartable by default, unless:
// 1. They are inline
// 2. They have a return value (may get relaxed in the future)
- // 3. They are a lambda (we use RestartableFunction<...> class for this instead)
+ // 3. They are a lambda (we use ComposableLambda<...> class for this instead)
// 4. They are annotated as @ComposableContract(restartable = false)
private fun IrFunction.shouldBeRestartable(): Boolean {
// Only insert observe scopes in non-empty composable function
@@ -661,9 +659,6 @@
)
)
return false
- if (it.isEmitInline(context.bindingContext)) {
- return false
- }
}
}
@@ -771,7 +766,7 @@
return declaration
}
- // Composable lambdas are always wrapped with a RestartableFunction class, which has its own
+ // Composable lambdas are always wrapped with a ComposableLambda class, which has its own
// group in the invoke call. As a result, composable lambdas:
// 1. receive no group at the root of their body
// 2. cannot have default parameters, so have no default handling
@@ -782,7 +777,7 @@
scope: Scope.FunctionScope,
changedParam: IrChangedBitMaskValue
): IrStatement {
- // no group, since restartableFunction should already create one
+ // no group, since composableLambda should already create one
// no default logic
val body = declaration.body!!
val skipPreamble = mutableStatementContainer()
@@ -1147,6 +1142,7 @@
// first we create the necessary local variables for default handling.
val setDefaults = mutableStatementContainer()
+ val skipDefaults = mutableStatementContainer()
parameters.forEachIndexed { index, param ->
val defaultValue = param.defaultValue
if (defaultParam != null && defaultValue != null) {
@@ -1191,12 +1187,42 @@
isVar = false,
exactName = true
).also {
- setDefaults.statements.add(
- irIf(
- condition = irGetBit(defaultParam, index),
- body = irSet(it, transformedDefault)
+ if (
+ !defaultExprIsStatic[index] &&
+ dirty is IrChangedBitMaskVariable
+ ) {
+ // if we are setting the parameter to the default expression and
+ // running the default expression again, and the expression isn't
+ // provably static, we can't be certain that the dirty value of
+ // SAME is going to be valid. We must mark it as UNCERTAIN. In order
+ // to avoid slot-table misalignment issues, we must mark it as
+ // UNCERTAIN even when we skip the defaults, so that any child
+ // function receives UNCERTAIN vs SAME/DIFFERENT deterministically.
+ setDefaults.statements.add(
+ irIf(
+ condition = irGetBit(defaultParam, index),
+ body = irBlock(
+ statements = listOf(
+ irSet(it, transformedDefault),
+ dirty.irSetSlotUncertain(index)
+ )
+ )
+ )
)
- )
+ skipDefaults.statements.add(
+ irIf(
+ condition = irGetBit(defaultParam, index),
+ body = dirty.irSetSlotUncertain(index)
+ )
+ )
+ } else {
+ setDefaults.statements.add(
+ irIf(
+ condition = irGetBit(defaultParam, index),
+ body = irSet(it, transformedDefault)
+ )
+ )
+ }
}
}
@@ -1240,11 +1266,16 @@
}
val defaultValueIsStatic = defaultExprIsStatic[index]
+ val callChanged = irChanged(irGet(scope.remappedParams[param]!!))
+ val isChanged = if (defaultParam != null && !defaultValueIsStatic)
+ irAndAnd(irIsProvided(defaultParam, index), callChanged)
+ else
+ callChanged
val modifyDirtyFromChangedResult = dirty.irOrSetBitsAtSlot(
index,
irIfThenElse(
context.irBuiltIns.intType,
- irChanged(irGet(scope.remappedParams[param]!!)),
+ isChanged,
// if the value has changed, update the bits in the slot to be
// "Different"
thenPart = irConst(ParamState.Different.bitsForSlot(index)),
@@ -1278,12 +1309,8 @@
// with an "Uncertain" state AND the value was provided. This is safe to do
// because this will remain true or false for *every* execution of the
// function, so we will never get a slot table misalignment as a result.
- val condition = if (defaultParam != null) irAndAnd(
- irIsProvided(defaultParam, index),
- irIsUncertain(changedParam, index)
- ) else irIsUncertain(changedParam, index)
irIf(
- condition = condition,
+ condition = irIsUncertain(changedParam, index),
body = modifyDirtyFromChangedResult
)
}
@@ -1378,7 +1405,12 @@
)
),
// composer.skipCurrentGroup()
- elsePart = irSkipCurrentGroup()
+ elsePart = irBlock(
+ statements = listOf(
+ irSkipCurrentGroup(),
+ *skipDefaults.statements.toTypedArray()
+ )
+ )
)
)
}
@@ -2242,13 +2274,6 @@
}
override fun visitCall(expression: IrCall): IrExpression {
- val emitMetadata = context.irTrace[
- ComposeWritableSlices.COMPOSABLE_EMIT_METADATA,
- expression
- ]
- if (emitMetadata != null) {
- return visitEmitCall(expression)
- }
if (expression.isTransformedComposableCall() || expression.isSyntheticComposableCall()) {
return visitComposableCall(expression)
}
@@ -2374,12 +2399,6 @@
return expression
}
- private fun visitEmitCall(expression: IrCall): IrExpression {
- encounteredComposableCall()
- // TODO(lmr): eventually, we want to handle emits in this transform
- return super.visitCall(expression)
- }
-
private fun visitKeyCall(expression: IrCall): IrExpression {
val keyArgs = mutableListOf<IrExpression>()
var blockArg: IrExpression? = null
@@ -2539,7 +2558,7 @@
return true
}
}
- if (symbol.descriptor.fqNameSafe == ComposeFqNames.restartableFunction) {
+ if (symbol.descriptor.fqNameSafe == ComposeFqNames.composableLambda) {
// calls to this function are generated by the compiler, and this
// function behaves similar to a remember call in that the result will
// _always_ be the same and the resulting type is _always_ stable, so
@@ -3265,6 +3284,17 @@
)
)
}
+
+ override fun irSetSlotUncertain(slot: Int): IrExpression {
+ val temp = temps[paramIndexForSlot(slot)]
+ return irSet(
+ temp,
+ irAnd(
+ irGet(temp),
+ irInv(irConst(ParamState.Static.bitsForSlot(slot)))
+ )
+ )
+ }
}
}
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeResolutionMetadataTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeResolutionMetadataTransformer.kt
deleted file mode 100644
index a675c2a..0000000
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeResolutionMetadataTransformer.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.plugins.kotlin.compiler.lower
-
-import androidx.compose.plugins.kotlin.ComposableEmitDescriptor
-import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.irTrace
-import org.jetbrains.kotlin.backend.common.FileLoweringPass
-import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
-import org.jetbrains.kotlin.ir.declarations.IrFile
-import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
-import org.jetbrains.kotlin.ir.expressions.IrCall
-import org.jetbrains.kotlin.ir.expressions.IrExpression
-import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
-import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
-
-class ComposeResolutionMetadataTransformer(val context: IrPluginContext) :
- IrElementTransformerVoid(),
- FileLoweringPass,
- ModuleLoweringPass {
-
- override fun lower(module: IrModuleFragment) {
- module.transformChildrenVoid(this)
- }
-
- override fun lower(irFile: IrFile) {
- irFile.transformChildrenVoid(this)
- }
-
- override fun visitCall(expression: IrCall): IrExpression {
-
- val descriptor = expression.symbol.descriptor
-
- if (descriptor is ComposableEmitDescriptor) {
- context.irTrace.record(
- ComposeWritableSlices.COMPOSABLE_EMIT_METADATA,
- expression,
- descriptor
- )
- }
-
- return super.visitCall(expression)
- }
-}
\ No newline at end of file
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt
index 848fa43..c09aea7 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt
@@ -19,9 +19,8 @@
import androidx.compose.plugins.kotlin.ComposeUtils
import androidx.compose.plugins.kotlin.ComposeUtils.composeInternalFqName
import androidx.compose.plugins.kotlin.analysis.ComposeWritableSlices
-import androidx.compose.plugins.kotlin.hasUntrackedAnnotation
+import androidx.compose.plugins.kotlin.composableTrackedContract
import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.peek
@@ -133,10 +132,10 @@
}
}
-const val RESTARTABLE_FUNCTION = "restartableFunction"
-const val RESTARTABLE_FUNCTION_N = "restartableFunctionN"
-const val RESTARTABLE_FUNCTION_INSTANCE = "restartableFunctionInstance"
-const val RESTARTABLE_FUNCTION_N_INSTANCE = "restartableFunctionNInstance"
+const val COMPOSABLE_LAMBDA = "composableLambda"
+const val COMPOSABLE_LAMBDA_N = "composableLambdaN"
+const val COMPOSABLE_LAMBDA_INSTANCE = "composableLambdaInstance"
+const val COMPOSABLE_LAMBDA_N_INSTANCE = "composableLambdaNInstance"
class ComposerLambdaMemoization(
context: IrPluginContext,
@@ -340,15 +339,15 @@
): IrExpression {
val function = expression.function
val argumentCount = function.descriptor.valueParameters.size
- val useRestartableFunctionN = argumentCount > MAX_RESTART_ARGUMENT_COUNT
+ val useComposableLambdaN = argumentCount > MAX_RESTART_ARGUMENT_COUNT
val restartFunctionFactory =
if (declarationContext.composable)
- if (useRestartableFunctionN)
- RESTARTABLE_FUNCTION_N
- else RESTARTABLE_FUNCTION
- else if (useRestartableFunctionN)
- RESTARTABLE_FUNCTION_N_INSTANCE
- else RESTARTABLE_FUNCTION_INSTANCE
+ if (useComposableLambdaN)
+ COMPOSABLE_LAMBDA_N
+ else COMPOSABLE_LAMBDA
+ else if (useComposableLambdaN)
+ COMPOSABLE_LAMBDA_N_INSTANCE
+ else COMPOSABLE_LAMBDA_INSTANCE
val restartFactorySymbol =
getTopLevelFunction(composeInternalFqName(restartFunctionFactory))
val irBuilder = DeclarationIrBuilder(context,
@@ -379,8 +378,8 @@
// tracked parameter
putValueArgument(index++, irBuilder.irBoolean(expression.isTracked()))
- // RestartableFunctionN requires the arity
- if (useRestartableFunctionN) {
+ // ComposableLambdaN requires the arity
+ if (useComposableLambdaN) {
// arity parameter
putValueArgument(index++, irBuilder.irInt(argumentCount))
}
@@ -501,16 +500,14 @@
)
)
return true
- if (it.isEmitInline(context.bindingContext)) {
- return true
- }
}
}
return false
}
private fun IrExpression?.isNullOrStable() = this == null || type.toKotlinType().isStable()
- private fun IrFunctionExpression.isTracked() = !function.descriptor.hasUntrackedAnnotation()
+ private fun IrFunctionExpression.isTracked() =
+ function.descriptor.composableTrackedContract() != false
}
// This must match the highest value of FunctionXX which is current Function22
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt
index 1f267cd..4d4e36f 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt
@@ -21,7 +21,6 @@
import androidx.compose.plugins.kotlin.generateSymbols
import androidx.compose.plugins.kotlin.hasComposableAnnotation
import androidx.compose.plugins.kotlin.irTrace
-import androidx.compose.plugins.kotlin.isEmitInline
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
@@ -612,19 +611,7 @@
override fun visitCall(expression: IrCall): IrExpression {
val expr = if (!isNestedScope) {
- expression.withComposerParamIfNeeded(composerParam).also { call ->
- if (
- fn.isInline &&
- call !== expression &&
- call.isInlineParameterLambdaInvoke()
- ) {
- context.irTrace.record(
- ComposeWritableSlices.IS_INLINE_COMPOSABLE_CALL,
- call,
- true
- )
- }
- }
+ expression.withComposerParamIfNeeded(composerParam)
} else
expression
return super.visitCall(expr)
@@ -669,13 +656,6 @@
}
private fun IrFunction.isEmitInlineChildrenLambda(): Boolean {
- descriptor.findPsi()?.let { psi ->
- (psi as? KtFunctionLiteral)?.let {
- if (it.isEmitInline(context.bindingContext)) {
- return true
- }
- }
- }
return false
}
}
diff --git a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt
index f8248af..68abc3b 100644
--- a/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt
+++ b/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/IrSourcePrinter.kt
@@ -16,7 +16,6 @@
package androidx.compose.plugins.kotlin.compiler.lower
-import androidx.compose.plugins.kotlin.ComposableEmitDescriptor
import androidx.compose.plugins.kotlin.KtxNameConventions
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -447,20 +446,15 @@
forceParameterNames: Boolean = false,
forceSingleLine: Boolean = false
) {
- val descriptor = symbol.descriptor
val arguments = mutableListOf<IrExpression>()
val paramNames = mutableListOf<String>()
var trailingLambda: IrExpression? = null
- val isEmit = descriptor is ComposableEmitDescriptor
- val isCompoundEmit = descriptor is ComposableEmitDescriptor && descriptor.hasChildren
- val isLeafEmit = isEmit && !isCompoundEmit
- var useParameterNames = forceParameterNames || isEmit
+ var useParameterNames = forceParameterNames
for (i in 0 until valueArgumentsCount) {
val arg = getValueArgument(i)
if (arg != null) {
val param = symbol.owner.valueParameters[i]
val isTrailingLambda = i == symbol.owner.valueParameters.size - 1 &&
- !isLeafEmit &&
(
arg is IrFunctionExpression ||
(arg is IrBlock && arg.origin == IrStatementOrigin.LAMBDA)
diff --git a/compose/compose-dispatch/OWNERS b/compose/compose-dispatch/OWNERS
new file mode 100644
index 0000000..1cd0c38
--- /dev/null
+++ b/compose/compose-dispatch/OWNERS
@@ -0,0 +1,4 @@
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/compose/compose-dispatch/api/0.1.0-dev15.txt b/compose/compose-dispatch/api/0.1.0-dev15.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/0.1.0-dev15.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+ public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+ method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+ method public android.view.Choreographer getChoreographer();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+ }
+
+ public static final class AndroidUiDispatcher.Companion {
+ method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+ method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+ property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+ property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+ }
+
+ public final class AndroidUiDispatcherKt {
+ }
+
+ public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+ ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+ method public android.view.Choreographer getChoreographer();
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public interface MonotonicFrameClock {
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public final class MonotonicFrameClockKt {
+ method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+}
+
diff --git a/compose/compose-dispatch/api/current.txt b/compose/compose-dispatch/api/current.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/current.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+ public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+ method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+ method public android.view.Choreographer getChoreographer();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+ }
+
+ public static final class AndroidUiDispatcher.Companion {
+ method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+ method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+ property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+ property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+ }
+
+ public final class AndroidUiDispatcherKt {
+ }
+
+ public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+ ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+ method public android.view.Choreographer getChoreographer();
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public interface MonotonicFrameClock {
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public final class MonotonicFrameClockKt {
+ method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+}
+
diff --git a/compose/compose-dispatch/api/public_plus_experimental_0.1.0-dev15.txt b/compose/compose-dispatch/api/public_plus_experimental_0.1.0-dev15.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/public_plus_experimental_0.1.0-dev15.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+ public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+ method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+ method public android.view.Choreographer getChoreographer();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+ }
+
+ public static final class AndroidUiDispatcher.Companion {
+ method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+ method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+ property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+ property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+ }
+
+ public final class AndroidUiDispatcherKt {
+ }
+
+ public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+ ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+ method public android.view.Choreographer getChoreographer();
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public interface MonotonicFrameClock {
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public final class MonotonicFrameClockKt {
+ method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+}
+
diff --git a/compose/compose-dispatch/api/public_plus_experimental_current.txt b/compose/compose-dispatch/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/public_plus_experimental_current.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+ public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+ method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+ method public android.view.Choreographer getChoreographer();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+ }
+
+ public static final class AndroidUiDispatcher.Companion {
+ method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+ method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+ property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+ property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+ }
+
+ public final class AndroidUiDispatcherKt {
+ }
+
+ public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+ ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+ method public android.view.Choreographer getChoreographer();
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public interface MonotonicFrameClock {
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public final class MonotonicFrameClockKt {
+ method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+}
+
diff --git a/compose/compose-dispatch/api/res-0.1.0-dev15.txt b/compose/compose-dispatch/api/res-0.1.0-dev15.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/compose-dispatch/api/res-0.1.0-dev15.txt
diff --git a/compose/compose-dispatch/api/res-current.txt b/compose/compose-dispatch/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/compose-dispatch/api/res-current.txt
diff --git a/compose/compose-dispatch/api/restricted_0.1.0-dev15.txt b/compose/compose-dispatch/api/restricted_0.1.0-dev15.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/restricted_0.1.0-dev15.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+ public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+ method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+ method public android.view.Choreographer getChoreographer();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+ }
+
+ public static final class AndroidUiDispatcher.Companion {
+ method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+ method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+ property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+ property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+ }
+
+ public final class AndroidUiDispatcherKt {
+ }
+
+ public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+ ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+ method public android.view.Choreographer getChoreographer();
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public interface MonotonicFrameClock {
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public final class MonotonicFrameClockKt {
+ method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+}
+
diff --git a/compose/compose-dispatch/api/restricted_current.txt b/compose/compose-dispatch/api/restricted_current.txt
new file mode 100644
index 0000000..ecb0640
--- /dev/null
+++ b/compose/compose-dispatch/api/restricted_current.txt
@@ -0,0 +1,37 @@
+// Signature format: 3.0
+package androidx.compose.dispatch {
+
+ public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
+ method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
+ method public android.view.Choreographer getChoreographer();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.dispatch.AndroidUiDispatcher.Companion Companion;
+ }
+
+ public static final class AndroidUiDispatcher.Companion {
+ method public androidx.compose.dispatch.AndroidUiDispatcher getCurrentThread();
+ method public androidx.compose.dispatch.AndroidUiDispatcher getMain();
+ property public final androidx.compose.dispatch.AndroidUiDispatcher CurrentThread;
+ property public final androidx.compose.dispatch.AndroidUiDispatcher Main;
+ }
+
+ public final class AndroidUiDispatcherKt {
+ }
+
+ public final class AndroidUiFrameClock implements androidx.compose.dispatch.MonotonicFrameClock {
+ ctor public AndroidUiFrameClock(android.view.Choreographer choreographer);
+ method public android.view.Choreographer getChoreographer();
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public interface MonotonicFrameClock {
+ method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+ public final class MonotonicFrameClockKt {
+ method public static suspend inline <R> Object? withFrameMillis(androidx.compose.dispatch.MonotonicFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ }
+
+}
+
diff --git a/compose/compose-dispatch/build.gradle b/compose/compose-dispatch/build.gradle
new file mode 100644
index 0000000..bf2cb7c
--- /dev/null
+++ b/compose/compose-dispatch/build.gradle
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("AndroidXUiPlugin")
+ id("com.android.library")
+ id("kotlin-multiplatform")
+}
+
+kotlin {
+ android()
+ jvm("desktop")
+
+ sourceSets {
+ commonMain.dependencies {
+ implementation(KOTLIN_STDLIB_COMMON)
+ api(KOTLIN_COROUTINES_CORE_COMMON)
+ }
+ jvmMain.dependencies {
+ implementation(KOTLIN_STDLIB)
+ api(KOTLIN_COROUTINES_CORE)
+ }
+ androidMain {
+ dependencies {
+ api "androidx.annotation:annotation:1.1.0"
+ implementation("androidx.core:core-ktx:1.1.0")
+ implementation(KOTLIN_COROUTINES_ANDROID)
+ }
+ dependsOn jvmMain
+ }
+
+ androidTest.dependencies {
+ implementation(ANDROIDX_TEST_RULES)
+ implementation(ANDROIDX_TEST_RUNNER)
+ implementation(JUNIT)
+ }
+
+ androidAndroidTest.dependencies {
+ implementation(ANDROIDX_TEST_RULES)
+ implementation(ANDROIDX_TEST_RUNNER)
+ implementation(ANDROIDX_TEST_EXT_KTX)
+ implementation(ANDROIDX_TEST_UIAUTOMATOR)
+ implementation(JUNIT)
+ }
+
+ desktopMain {
+ dependsOn jvmMain
+ }
+ }
+}
+
+android {
+ buildTypes {
+ debug {
+ testCoverageEnabled = false
+ }
+ release {
+ testCoverageEnabled = false
+ }
+ }
+}
+
+androidx {
+ name = "Compose Dispatch"
+ publish = Publish.SNAPSHOT_AND_RELEASE
+ mavenVersion = LibraryVersions.COMPOSE
+ mavenGroup = LibraryGroups.COMPOSE
+ inceptionYear = "2020"
+ description = "Platform timing and event dispatch utilities"
+}
+
+tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions {
+ freeCompilerArgs += [
+ "-Xuse-experimental=kotlin.Experimental"
+ ]
+ useIR = true
+ }
+}
diff --git a/compose/compose-dispatch/src/androidAndroidTest/AndroidManifest.xml b/compose/compose-dispatch/src/androidAndroidTest/AndroidManifest.xml
new file mode 100644
index 0000000..a6c2833
--- /dev/null
+++ b/compose/compose-dispatch/src/androidAndroidTest/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.compose.dispatch.test">
+ <application>
+ <activity android:name="androidx.compose.dispatch.TestActivity" />
+ </application>
+</manifest>
diff --git a/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/AndroidUiDispatcherTest.kt b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/AndroidUiDispatcherTest.kt
new file mode 100644
index 0000000..c031c35
--- /dev/null
+++ b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/AndroidUiDispatcherTest.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.dispatch
+
+import android.graphics.Rect
+import android.view.Choreographer
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup.LayoutParams
+import androidx.core.view.doOnLayout
+import androidx.test.ext.junit.rules.activityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class AndroidUiDispatcherTest {
+ @get:Rule
+ val rule = activityScenarioRule<TestActivity>()
+
+ @Test
+ fun currentThreadIsMainOnMainThread() = runBlocking(Dispatchers.Main) {
+ assertSame(AndroidUiDispatcher.Main, AndroidUiDispatcher.CurrentThread)
+ }
+
+ @Test
+ fun runsBeforeFrameCallback() = runBlocking(Dispatchers.Main) {
+ rule.scenario.onActivity {
+ // Force creation of decor view to ensure we have a frame scheduled
+ it.window.decorView
+ }
+
+ var ranOnUiDispatcher = false
+ launch(AndroidUiDispatcher.Main) { ranOnUiDispatcher = true }
+
+ val choreographerResult = CompletableDeferred<Boolean>()
+ Choreographer.getInstance().postFrameCallback {
+ choreographerResult.complete(ranOnUiDispatcher)
+ }
+
+ assertTrue("UI dispatcher ran before choreographer frame", choreographerResult.await())
+ }
+
+ /**
+ * Verify that [AndroidUiDispatcher] will run a resumed continuation before
+ * the next frame is drawn, even if that continuation is resumed during the dispatch of
+ * batched input. Batched input is dispatched during an atomic sequence of events handled
+ * by the [Choreographer] of input => animation callbacks => measure => layout => draw,
+ * which will cause dispatchers that schedule entirely based on [android.os.Handler] messages
+ * to miss the current frame.
+ *
+ * This test also verifies that a call to [AndroidUiDispatcher.frameClock]'s
+ * [MonotonicFrameClock.withFrameNanos] will resume in time to make the current frame if called
+ * from the situation described above, and that subsequent calls will wait until the next frame.
+ */
+ @Test
+ fun runsBeforeFrameDispatchedByInput() = runBlocking {
+ val ranInputJobOnFrame = CompletableDeferred<Int>()
+ val viewTouchedOnFrame = CompletableDeferred<Int>()
+ val withFrameOnFrame = CompletableDeferred<Int>()
+ val withFrameSecondCall = CompletableDeferred<Int>()
+ val layoutRect = CompletableDeferred<Rect>()
+ var preDrawCount = 0
+ rule.scenario.onActivity { activity ->
+ activity.setContentView(
+ View(activity).apply {
+ setOnTouchListener { _, motionEvent ->
+ if (motionEvent.action != MotionEvent.ACTION_UP) {
+ return@setOnTouchListener true
+ }
+ viewTouchedOnFrame.complete(preDrawCount)
+ launch(AndroidUiDispatcher.Main) {
+ ranInputJobOnFrame.complete(preDrawCount)
+ AndroidUiDispatcher.Main.frameClock.withFrameNanos {
+ withFrameOnFrame.complete(preDrawCount)
+ }
+ AndroidUiDispatcher.Main.frameClock.withFrameNanos {
+ withFrameSecondCall.complete(preDrawCount)
+ }
+ }
+ invalidate()
+ true
+ }
+ viewTreeObserver.addOnPreDrawListener {
+ preDrawCount++
+ true
+ }
+ doOnLayout { view ->
+ val rect = Rect()
+ view.getGlobalVisibleRect(rect)
+ layoutRect.complete(rect)
+ }
+ },
+ LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
+ )
+ }
+
+ with(UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())) {
+ // Use a swipe event with many steps to force the input dispatcher into batched mode.
+ // A simple click here will not force batched mode of input dispatch to the view
+ // hierarchy and the test will pass using a solely Handler-based dispatcher.
+ // Batched mode will wait to dispatch events until the frame begins, causing
+ // a Handler message to miss the frame, but AndroidUiDispatchers.Main should resume
+ // in the same frame if the resume was triggered by the input event.
+ val rect = layoutRect.await()
+ swipe(rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1, 30)
+ }
+
+ withTimeout(3_000) {
+ val viewTouched = viewTouchedOnFrame.await()
+ val inputJob = ranInputJobOnFrame.await()
+ assertNotEquals(0, viewTouched)
+ assertNotEquals(0, inputJob)
+ assertEquals(
+ "touch and launched job resume happened on same frame",
+ viewTouched,
+ inputJob
+ )
+ assertEquals(
+ "withFrame ran on the same frame where it was called",
+ inputJob,
+ withFrameOnFrame.await()
+ )
+ assertEquals(
+ "second withFrame call was invoked on the very next frame",
+ inputJob + 1,
+ withFrameSecondCall.await()
+ )
+ }
+ }
+}
diff --git a/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/TestActivity.kt b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/TestActivity.kt
new file mode 100644
index 0000000..4afcf14
--- /dev/null
+++ b/compose/compose-dispatch/src/androidAndroidTest/kotlin/androidx/compose/dispatch/TestActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.dispatch
+
+import androidx.core.app.ComponentActivity
+
+class TestActivity : ComponentActivity()
\ No newline at end of file
diff --git a/compose/compose-dispatch/src/androidMain/AndroidManifest.xml b/compose/compose-dispatch/src/androidMain/AndroidManifest.xml
new file mode 100644
index 0000000..c63b040
--- /dev/null
+++ b/compose/compose-dispatch/src/androidMain/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest package="androidx.compose.dispatch"/>
diff --git a/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiDispatcher.kt b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiDispatcher.kt
new file mode 100644
index 0000000..e3d3a05
--- /dev/null
+++ b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiDispatcher.kt
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.dispatch
+
+import android.os.Looper
+import android.view.Choreographer
+import androidx.core.os.HandlerCompat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlin.coroutines.CoroutineContext
+
+/**
+ * A [CoroutineDispatcher] that will perform dispatch during a [handler] callback or
+ * [choreographer]'s animation frame stage, whichever comes first. Use [Main] to obtain
+ * a dispatcher for the process's main thread (i.e. the activity thread) or [CurrentThread]
+ * to obtain a dispatcher for the current thread.
+ */
+// Implementation note: the constructor is private to direct users toward the companion object
+// accessors for the main/current threads. A choreographer must be obtained from its current
+// thread as per the only public API surface for obtaining one as of this writing, and the
+// choreographer and handler must match. Constructing an AndroidUiDispatcher with a handler
+// not marked as async will adversely affect dispatch behavior but not to the point of
+// incorrectness; more operations would be deferred to the choreographer frame as racing handler
+// messages would wait behind a frame barrier.
+@OptIn(ExperimentalStdlibApi::class)
+class AndroidUiDispatcher private constructor(
+ val choreographer: Choreographer,
+ private val handler: android.os.Handler
+) : CoroutineDispatcher() {
+
+ // Guards all properties in this class
+ private val lock = Any()
+
+ private val toRunTrampolined = ArrayDeque<Runnable>()
+ private var toRunOnFrame = mutableListOf<Choreographer.FrameCallback>()
+ private var spareToRunOnFrame = mutableListOf<Choreographer.FrameCallback>()
+ private var scheduledTrampolineDispatch = false
+ private var scheduledFrameDispatch = false
+
+ private val dispatchCallback = object : Choreographer.FrameCallback, Runnable {
+ override fun run() {
+ performTrampolineDispatch()
+ synchronized(lock) {
+ if (toRunOnFrame.isEmpty()) {
+ choreographer.removeFrameCallback(this)
+ scheduledFrameDispatch = false
+ }
+ }
+ }
+
+ override fun doFrame(frameTimeNanos: Long) {
+ handler.removeCallbacks(this)
+ performTrampolineDispatch()
+ performFrameDispatch(frameTimeNanos)
+ }
+ }
+
+ private fun nextTask(): Runnable? = synchronized(lock) {
+ toRunTrampolined.removeFirstOrNull()
+ }
+
+ private fun performTrampolineDispatch() {
+ do {
+ var task = nextTask()
+ while (task != null) {
+ task.run()
+ task = nextTask()
+ }
+ } while (
+ // We don't dispatch holding the lock so that other tasks can get in on our
+ // trampolining time slice, but once we're done, make sure nothing added a new task
+ // before we set scheduledDispatch = false, which would prevent the next dispatch
+ // from being correctly scheduled. Loop to run these stragglers now.
+ synchronized(lock) {
+ if (toRunTrampolined.isEmpty()) {
+ scheduledTrampolineDispatch = false
+ false
+ } else true
+ }
+ )
+ }
+
+ private fun performFrameDispatch(frameTimeNanos: Long) {
+ val toRun = synchronized(lock) {
+ if (!scheduledFrameDispatch) return
+ scheduledFrameDispatch = false
+ val result = toRunOnFrame
+ toRunOnFrame = spareToRunOnFrame
+ spareToRunOnFrame = result
+ result
+ }
+ for (i in 0 until toRun.size) {
+ // This callback can't throw, see AndroidUiCompositionFrameClock
+ toRun[i].doFrame(frameTimeNanos)
+ }
+ toRun.clear()
+ }
+
+ internal fun postFrameCallback(callback: Choreographer.FrameCallback) {
+ synchronized(lock) {
+ toRunOnFrame.add(callback)
+ if (!scheduledFrameDispatch) {
+ scheduledFrameDispatch = true
+ choreographer.postFrameCallback(dispatchCallback)
+ }
+ }
+ }
+
+ internal fun removeFrameCallback(callback: Choreographer.FrameCallback) {
+ synchronized(lock) {
+ toRunOnFrame.remove(callback)
+ }
+ }
+
+ /**
+ * A [MonotonicFrameClock] associated with this [AndroidUiDispatcher]'s [choreographer]
+ * that may be used to await [Choreographer] frame dispatch.
+ */
+ val frameClock: MonotonicFrameClock = AndroidUiFrameClock(choreographer)
+
+ override fun dispatch(context: CoroutineContext, block: Runnable) {
+ synchronized(lock) {
+ toRunTrampolined.addLast(block)
+ if (!scheduledTrampolineDispatch) {
+ scheduledTrampolineDispatch = true
+ handler.post(dispatchCallback)
+ if (!scheduledFrameDispatch) {
+ scheduledFrameDispatch = true
+ choreographer.postFrameCallback(dispatchCallback)
+ }
+ }
+ }
+ }
+
+ companion object {
+ /**
+ * The [AndroidUiDispatcher] for the process's main thread.
+ */
+ val Main by lazy {
+ AndroidUiDispatcher(
+ if (isMainThread()) Choreographer.getInstance()
+ else runBlocking(Dispatchers.Main) { Choreographer.getInstance() },
+ HandlerCompat.createAsync(Looper.getMainLooper())
+ )
+ }
+
+ private val currentThread: ThreadLocal<AndroidUiDispatcher> =
+ object : ThreadLocal<AndroidUiDispatcher>() {
+ override fun initialValue(): AndroidUiDispatcher = AndroidUiDispatcher(
+ Choreographer.getInstance(),
+ HandlerCompat.createAsync(Looper.myLooper()
+ ?: error("no Looper on this thread"))
+ )
+ }
+
+ /**
+ * The canonical [AndroidUiDispatcher] for the calling thread. Returns [Main] if accessed
+ * from the process's main thread.
+ *
+ * Throws [IllegalArgumentException] if the calling thread does not have
+ * both a [Choreographer] and an active [Looper].
+ */
+ val CurrentThread: AndroidUiDispatcher get() = if (isMainThread()) Main else {
+ currentThread.get() ?: error("no AndroidUiDispatcher for this thread")
+ }
+ }
+}
+
+private fun isMainThread() = Looper.myLooper() === Looper.getMainLooper()
diff --git a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiCompositionFrameClock.kt b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiFrameClock.kt
similarity index 88%
rename from compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiCompositionFrameClock.kt
rename to compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiFrameClock.kt
index 8651c94..5f04241 100644
--- a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiCompositionFrameClock.kt
+++ b/compose/compose-dispatch/src/androidMain/kotlin/androidx/compose/dispatch/AndroidUiFrameClock.kt
@@ -14,27 +14,23 @@
* limitations under the License.
*/
-package androidx.compose
+package androidx.compose.dispatch
import android.view.Choreographer
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.coroutineContext
-/**
- * A [CompositionFrameClock] driven by an [android.view.Choreographer].
- */
-class AndroidUiCompositionFrameClock(
+class AndroidUiFrameClock(
val choreographer: Choreographer
-) : CompositionFrameClock {
-
+) : MonotonicFrameClock {
override suspend fun <R> withFrameNanos(
onFrame: (Long) -> R
): R {
val uiDispatcher = coroutineContext[ContinuationInterceptor] as? AndroidUiDispatcher
return suspendCancellableCoroutine { co ->
// Important: this callback won't throw, and AndroidUiDispatcher counts on it.
- val callback = ChoreographerFrameCallback { frameTimeNanos ->
+ val callback = Choreographer.FrameCallback { frameTimeNanos ->
co.resumeWith(runCatching { onFrame(frameTimeNanos) })
}
@@ -54,4 +50,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/compose/compose-dispatch/src/commonMain/kotlin/androidx/compose/dispatch/MonotonicFrameClock.kt b/compose/compose-dispatch/src/commonMain/kotlin/androidx/compose/dispatch/MonotonicFrameClock.kt
new file mode 100644
index 0000000..2561001
--- /dev/null
+++ b/compose/compose-dispatch/src/commonMain/kotlin/androidx/compose/dispatch/MonotonicFrameClock.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.dispatch
+
+/**
+ * Provides a time source for display frames and the ability to perform an action on the next frame.
+ * This may be used for matching timing with the refresh rate of a display or otherwise
+ * synchronizing work with a desired frame rate.
+ */
+interface MonotonicFrameClock {
+ /**
+ * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
+ * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
+ * [onFrame].
+ *
+ * `frameTimeNanos` should be used when calculating animation time deltas from frame to frame
+ * as it may be normalized to the target time for the frame, not necessarily a direct,
+ * "now" value.
+ *
+ * The time base of the value provided by [withFrameNanos] is implementation defined.
+ * Time values provided are monotonically increasing; after a call to [withFrameNanos]
+ * completes it must not provide the same value again for a subsequent call.
+ */
+ suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R
+}
+
+/**
+ * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
+ * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
+ * [onFrame].
+ *
+ * `frameTimeNanos` should be used when calculating animation time deltas from frame to frame
+ * as it may be normalized to the target time for the frame, not necessarily a direct,
+ * "now" value.
+ *
+ * The time base of the value provided by [MonotonicFrameClock.withFrameMillis] is
+ * implementation defined. Time values provided are monotonically increasing; after a call to
+ * [MonotonicFrameClock.withFrameMillis] completes it must not provide the same value again for
+ * a subsequent call.
+ */
+@Suppress("UnnecessaryLambdaCreation")
+suspend inline fun <R> MonotonicFrameClock.withFrameMillis(
+ crossinline onFrame: (frameTimeMillis: Long) -> R
+): R = withFrameNanos { onFrame(it / 1_000_000L) }
diff --git a/compose/compose-runtime/api/0.1.0-dev15.txt b/compose/compose-runtime/api/0.1.0-dev15.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/0.1.0-dev15.txt
+++ b/compose/compose-runtime/api/0.1.0-dev15.txt
@@ -1,13 +1,26 @@
// Signature format: 3.0
package androidx.compose {
+ @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+ ctor public AbstractApplier(T! root);
+ method public void down(T? node);
+ method public T! getCurrent();
+ method public final T! getRoot();
+ method protected final void move(java.util.List<T>, int from, int to, int count);
+ method protected final void remove(java.util.List<T>, int index, int count);
+ method public void reset();
+ method public void setCurrent(T! p);
+ method public void up();
+ property public T! current;
+ }
+
public final class ActualAndroidKt {
}
public final class ActualJvmKt {
}
- @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+ @androidx.compose.Stable public abstract sealed class Ambient<T> {
method public final inline T! getCurrent();
property public final inline T! current;
}
@@ -25,29 +38,7 @@
property public final boolean valid;
}
- public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
- ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
- method public android.view.Choreographer getChoreographer();
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- }
-
- public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
- method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
- method public android.view.Choreographer getChoreographer();
- method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
- property public final androidx.compose.CompositionFrameClock compositionFrameClock;
- field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
- }
-
- public static final class AndroidUiDispatcher.Companion {
- method public androidx.compose.AndroidUiDispatcher getCurrentThread();
- method public androidx.compose.AndroidUiDispatcher getMain();
- property public final androidx.compose.AndroidUiDispatcher CurrentThread;
- property public final androidx.compose.AndroidUiDispatcher Main;
- }
-
- @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
- ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+ @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
method public void down(N? node);
method public N! getCurrent();
method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
method public void remove(int index, int count);
method public void reset();
method public void up();
- property public final N! current;
- }
-
- @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
- method public void end(N?, N? instance, N? parent);
- method public void insertAt(N?, int index, N? instance);
- method public void move(N?, int from, int to, int count);
- method public void removeAt(N?, int index, int count);
- method public void start(N?, N? instance);
+ property public abstract N! current;
}
public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
}
- @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
+ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
}
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
method public abstract boolean readonly() default false;
method public abstract boolean restartable() default true;
+ method public abstract boolean tracked() default true;
}
@kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
}
- public class Composer<N> {
+ public final class Composer<N> {
ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
- method @androidx.compose.InternalComposeApi public final void applyChanges();
- method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
- method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
- method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
- method @androidx.compose.ComposeCompilerApi public final void endDefaults();
- method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
- method @androidx.compose.ComposeCompilerApi public final void endNode();
- method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
- method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
- method public final int getCurrentCompoundKeyHash();
- method public final boolean getDefaultsInvalid();
- method public final boolean getInserting();
- method public final androidx.compose.Recomposer getRecomposer();
- method public final boolean getSkipping();
- method public final androidx.compose.SlotTable getSlotTable();
- method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
- method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
- method @androidx.compose.InternalComposeApi public final boolean recompose();
- method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
- method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
- method @androidx.compose.ComposeCompilerApi public final void startDefaults();
- method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
- method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
- method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final N! useNode();
+ method @androidx.compose.InternalComposeApi public void applyChanges();
+ method @Deprecated public inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+ method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+ method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+ method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+ method @androidx.compose.ComposeCompilerApi public void endDefaults();
+ method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+ method @androidx.compose.ComposeCompilerApi public void endNode();
+ method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+ method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+ method public androidx.compose.Applier<N> getApplier();
+ method public int getCurrentCompoundKeyHash();
+ method public boolean getDefaultsInvalid();
+ method public boolean getInserting();
+ method public androidx.compose.Recomposer getRecomposer();
+ method public boolean getSkipping();
+ method public androidx.compose.SlotTable getSlotTable();
+ method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+ method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+ method @androidx.compose.InternalComposeApi public boolean recompose();
+ method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+ method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+ method @androidx.compose.ComposeCompilerApi public void startDefaults();
+ method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+ method @androidx.compose.ComposeCompilerApi public void startNode();
+ method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public N! useNode();
property public final int currentCompoundKeyHash;
property public final boolean defaultsInvalid;
property public final boolean inserting;
@@ -151,20 +135,11 @@
}
public final class ComposerKt {
- method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static androidx.compose.Composer<?> getComposer();
method public static androidx.compose.Composer<?> getCurrentComposer();
}
- public final class ComposerUpdater<N, T extends N> {
- ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
- method public androidx.compose.Composer<N> getComposer();
- method public T! getNode();
- method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- }
-
@Deprecated public interface ComposerValidator {
method @Deprecated public boolean changed(int value);
method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
- public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+ public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
ctor public CompositionCoroutineScope();
method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
}
- public interface CompositionFrameClock {
+ @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionFrameClockKt {
method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
- method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionKt {
- method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
}
public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
}
+ public final class EmitKt {
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+ }
+
public final class ExpectKt {
}
@@ -241,7 +221,7 @@
method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
method public void nextFrame();
method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
- field public static final androidx.compose.FrameManager! INSTANCE;
+ field public static final androidx.compose.FrameManager INSTANCE;
}
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
}
- public final class NullCompilationScope {
- method public kotlin.Unit getComposer();
+ @Deprecated public final class NullCompilationScope {
+ method @Deprecated public kotlin.Unit getComposer();
property public final kotlin.Unit composer;
- field public static final androidx.compose.NullCompilationScope! INSTANCE;
+ field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
}
public final class ObserveKt {
@@ -316,7 +296,7 @@
method public void removeValue(V value);
}
- @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+ @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
}
@@ -332,12 +312,12 @@
public final class Recomposer {
ctor public Recomposer();
method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public androidx.compose.CompositionFrameClock getFrameClock();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
method public boolean hasPendingChanges();
- method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
- property public final androidx.compose.CompositionFrameClock frameClock;
- field public static final androidx.compose.Recomposer.Companion! Companion;
+ method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.Recomposer.Companion Companion;
}
public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
}
public final class RecomposerKt {
- method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
}
public final class RememberKt {
@@ -430,7 +410,7 @@
method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
property public final int size;
- field public static final androidx.compose.SlotTable.Companion! Companion;
+ field public static final androidx.compose.SlotTable.Companion Companion;
}
@androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
method public abstract Class<?>[] types();
}
- @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ }
+
+ public final class Updater<T> {
+ ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+ method public androidx.compose.Composer<?> getComposer();
+ method public T! getNode();
+ method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+ method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+ method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
}
}
@@ -661,8 +652,8 @@
package androidx.compose.internal {
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
- ctor public RestartableFunction(int key, boolean tracked);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+ ctor public ComposableLambda(int key, boolean tracked);
method public int getKey();
method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
method public void update(Object block);
}
- public final class RestartableFunctionKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+ public final class ComposableLambdaKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
}
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
- ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+ ctor public ComposableLambdaN(int key, boolean tracked, int arity);
method public int getArity();
method public int getKey();
method public R! invoke(java.lang.Object?... args);
method public void update(Object block);
}
- public final class RestartableFunctionNKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+ public final class ComposableLambdaNKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
}
}
diff --git a/compose/compose-runtime/api/api_lint.ignore b/compose/compose-runtime/api/api_lint.ignore
index 215da53..bd61dc8 100644
--- a/compose/compose-runtime/api/api_lint.ignore
+++ b/compose/compose-runtime/api/api_lint.ignore
@@ -41,10 +41,6 @@
Exceptions must be named `FooException`, was `FrameAborted`
-KotlinOperator: androidx.compose.ComposerUpdater#set(V, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit>):
- Note that adding the `operator` keyword would allow calling this method using operator syntax
-KotlinOperator: androidx.compose.ComposerUpdater#set(int, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit>):
- Note that adding the `operator` keyword would allow calling this method using operator syntax
KotlinOperator: androidx.compose.SlotReader#get(androidx.compose.Anchor):
Note that adding the `operator` keyword would allow calling this method using operator syntax
KotlinOperator: androidx.compose.SlotReader#get(int):
@@ -53,6 +49,10 @@
Note that adding the `operator` keyword would allow calling this method using operator syntax
KotlinOperator: androidx.compose.SlotWriter#get(int):
Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.compose.Updater#set(V, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit>):
+ Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.compose.Updater#set(int, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit>):
+ Note that adding the `operator` keyword would allow calling this method using operator syntax
MissingNullability: androidx.compose.BuildableMap#containsKey(Object) parameter #0:
@@ -76,6 +76,7 @@
NoByteOrShort: androidx.compose.Composer#changed(short) parameter #0:
Should avoid odd sized primitives; use `int` instead of `short` in parameter value in androidx.compose.Composer.changed(short value)
+
NotCloseable: androidx.compose.SlotReader:
Classes that release resources (close()) should implement AutoClosable and CloseGuard: class androidx.compose.SlotReader
NotCloseable: androidx.compose.SlotWriter:
diff --git a/compose/compose-runtime/api/current.txt b/compose/compose-runtime/api/current.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/current.txt
+++ b/compose/compose-runtime/api/current.txt
@@ -1,13 +1,26 @@
// Signature format: 3.0
package androidx.compose {
+ @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+ ctor public AbstractApplier(T! root);
+ method public void down(T? node);
+ method public T! getCurrent();
+ method public final T! getRoot();
+ method protected final void move(java.util.List<T>, int from, int to, int count);
+ method protected final void remove(java.util.List<T>, int index, int count);
+ method public void reset();
+ method public void setCurrent(T! p);
+ method public void up();
+ property public T! current;
+ }
+
public final class ActualAndroidKt {
}
public final class ActualJvmKt {
}
- @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+ @androidx.compose.Stable public abstract sealed class Ambient<T> {
method public final inline T! getCurrent();
property public final inline T! current;
}
@@ -25,29 +38,7 @@
property public final boolean valid;
}
- public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
- ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
- method public android.view.Choreographer getChoreographer();
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- }
-
- public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
- method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
- method public android.view.Choreographer getChoreographer();
- method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
- property public final androidx.compose.CompositionFrameClock compositionFrameClock;
- field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
- }
-
- public static final class AndroidUiDispatcher.Companion {
- method public androidx.compose.AndroidUiDispatcher getCurrentThread();
- method public androidx.compose.AndroidUiDispatcher getMain();
- property public final androidx.compose.AndroidUiDispatcher CurrentThread;
- property public final androidx.compose.AndroidUiDispatcher Main;
- }
-
- @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
- ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+ @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
method public void down(N? node);
method public N! getCurrent();
method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
method public void remove(int index, int count);
method public void reset();
method public void up();
- property public final N! current;
- }
-
- @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
- method public void end(N?, N? instance, N? parent);
- method public void insertAt(N?, int index, N? instance);
- method public void move(N?, int from, int to, int count);
- method public void removeAt(N?, int index, int count);
- method public void start(N?, N? instance);
+ property public abstract N! current;
}
public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
}
- @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
+ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
}
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
method public abstract boolean readonly() default false;
method public abstract boolean restartable() default true;
+ method public abstract boolean tracked() default true;
}
@kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
}
- public class Composer<N> {
+ public final class Composer<N> {
ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
- method @androidx.compose.InternalComposeApi public final void applyChanges();
- method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
- method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
- method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
- method @androidx.compose.ComposeCompilerApi public final void endDefaults();
- method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
- method @androidx.compose.ComposeCompilerApi public final void endNode();
- method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
- method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
- method public final int getCurrentCompoundKeyHash();
- method public final boolean getDefaultsInvalid();
- method public final boolean getInserting();
- method public final androidx.compose.Recomposer getRecomposer();
- method public final boolean getSkipping();
- method public final androidx.compose.SlotTable getSlotTable();
- method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
- method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
- method @androidx.compose.InternalComposeApi public final boolean recompose();
- method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
- method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
- method @androidx.compose.ComposeCompilerApi public final void startDefaults();
- method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
- method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
- method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final N! useNode();
+ method @androidx.compose.InternalComposeApi public void applyChanges();
+ method @Deprecated public inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+ method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+ method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+ method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+ method @androidx.compose.ComposeCompilerApi public void endDefaults();
+ method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+ method @androidx.compose.ComposeCompilerApi public void endNode();
+ method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+ method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+ method public androidx.compose.Applier<N> getApplier();
+ method public int getCurrentCompoundKeyHash();
+ method public boolean getDefaultsInvalid();
+ method public boolean getInserting();
+ method public androidx.compose.Recomposer getRecomposer();
+ method public boolean getSkipping();
+ method public androidx.compose.SlotTable getSlotTable();
+ method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+ method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+ method @androidx.compose.InternalComposeApi public boolean recompose();
+ method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+ method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+ method @androidx.compose.ComposeCompilerApi public void startDefaults();
+ method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+ method @androidx.compose.ComposeCompilerApi public void startNode();
+ method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public N! useNode();
property public final int currentCompoundKeyHash;
property public final boolean defaultsInvalid;
property public final boolean inserting;
@@ -151,20 +135,11 @@
}
public final class ComposerKt {
- method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static androidx.compose.Composer<?> getComposer();
method public static androidx.compose.Composer<?> getCurrentComposer();
}
- public final class ComposerUpdater<N, T extends N> {
- ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
- method public androidx.compose.Composer<N> getComposer();
- method public T! getNode();
- method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- }
-
@Deprecated public interface ComposerValidator {
method @Deprecated public boolean changed(int value);
method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
- public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+ public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
ctor public CompositionCoroutineScope();
method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
}
- public interface CompositionFrameClock {
+ @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionFrameClockKt {
method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
- method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionKt {
- method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
}
public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
}
+ public final class EmitKt {
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+ }
+
public final class ExpectKt {
}
@@ -241,7 +221,7 @@
method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
method public void nextFrame();
method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
- field public static final androidx.compose.FrameManager! INSTANCE;
+ field public static final androidx.compose.FrameManager INSTANCE;
}
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
}
- public final class NullCompilationScope {
- method public kotlin.Unit getComposer();
+ @Deprecated public final class NullCompilationScope {
+ method @Deprecated public kotlin.Unit getComposer();
property public final kotlin.Unit composer;
- field public static final androidx.compose.NullCompilationScope! INSTANCE;
+ field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
}
public final class ObserveKt {
@@ -316,7 +296,7 @@
method public void removeValue(V value);
}
- @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+ @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
}
@@ -332,12 +312,12 @@
public final class Recomposer {
ctor public Recomposer();
method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public androidx.compose.CompositionFrameClock getFrameClock();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
method public boolean hasPendingChanges();
- method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
- property public final androidx.compose.CompositionFrameClock frameClock;
- field public static final androidx.compose.Recomposer.Companion! Companion;
+ method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.Recomposer.Companion Companion;
}
public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
}
public final class RecomposerKt {
- method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
}
public final class RememberKt {
@@ -430,7 +410,7 @@
method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
property public final int size;
- field public static final androidx.compose.SlotTable.Companion! Companion;
+ field public static final androidx.compose.SlotTable.Companion Companion;
}
@androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
method public abstract Class<?>[] types();
}
- @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ }
+
+ public final class Updater<T> {
+ ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+ method public androidx.compose.Composer<?> getComposer();
+ method public T! getNode();
+ method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+ method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+ method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
}
}
@@ -661,8 +652,8 @@
package androidx.compose.internal {
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
- ctor public RestartableFunction(int key, boolean tracked);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+ ctor public ComposableLambda(int key, boolean tracked);
method public int getKey();
method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
method public void update(Object block);
}
- public final class RestartableFunctionKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+ public final class ComposableLambdaKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
}
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
- ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+ ctor public ComposableLambdaN(int key, boolean tracked, int arity);
method public int getArity();
method public int getKey();
method public R! invoke(java.lang.Object?... args);
method public void update(Object block);
}
- public final class RestartableFunctionNKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+ public final class ComposableLambdaNKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
}
}
diff --git a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_0.1.0-dev15.txt
@@ -1,13 +1,26 @@
// Signature format: 3.0
package androidx.compose {
+ @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+ ctor public AbstractApplier(T! root);
+ method public void down(T? node);
+ method public T! getCurrent();
+ method public final T! getRoot();
+ method protected final void move(java.util.List<T>, int from, int to, int count);
+ method protected final void remove(java.util.List<T>, int index, int count);
+ method public void reset();
+ method public void setCurrent(T! p);
+ method public void up();
+ property public T! current;
+ }
+
public final class ActualAndroidKt {
}
public final class ActualJvmKt {
}
- @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+ @androidx.compose.Stable public abstract sealed class Ambient<T> {
method public final inline T! getCurrent();
property public final inline T! current;
}
@@ -25,29 +38,7 @@
property public final boolean valid;
}
- public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
- ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
- method public android.view.Choreographer getChoreographer();
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- }
-
- public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
- method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
- method public android.view.Choreographer getChoreographer();
- method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
- property public final androidx.compose.CompositionFrameClock compositionFrameClock;
- field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
- }
-
- public static final class AndroidUiDispatcher.Companion {
- method public androidx.compose.AndroidUiDispatcher getCurrentThread();
- method public androidx.compose.AndroidUiDispatcher getMain();
- property public final androidx.compose.AndroidUiDispatcher CurrentThread;
- property public final androidx.compose.AndroidUiDispatcher Main;
- }
-
- @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
- ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+ @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
method public void down(N? node);
method public N! getCurrent();
method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
method public void remove(int index, int count);
method public void reset();
method public void up();
- property public final N! current;
- }
-
- @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
- method public void end(N?, N? instance, N? parent);
- method public void insertAt(N?, int index, N? instance);
- method public void move(N?, int from, int to, int count);
- method public void removeAt(N?, int index, int count);
- method public void start(N?, N? instance);
+ property public abstract N! current;
}
public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
}
- @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
+ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
}
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
method public abstract boolean readonly() default false;
method public abstract boolean restartable() default true;
+ method public abstract boolean tracked() default true;
}
@kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
}
- public class Composer<N> {
+ public final class Composer<N> {
ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
- method @androidx.compose.InternalComposeApi public final void applyChanges();
- method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
- method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
- method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
- method @androidx.compose.ComposeCompilerApi public final void endDefaults();
- method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
- method @androidx.compose.ComposeCompilerApi public final void endNode();
- method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
- method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
- method public final int getCurrentCompoundKeyHash();
- method public final boolean getDefaultsInvalid();
- method public final boolean getInserting();
- method public final androidx.compose.Recomposer getRecomposer();
- method public final boolean getSkipping();
- method public final androidx.compose.SlotTable getSlotTable();
- method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
- method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
- method @androidx.compose.InternalComposeApi public final boolean recompose();
- method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
- method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
- method @androidx.compose.ComposeCompilerApi public final void startDefaults();
- method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
- method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
- method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final N! useNode();
+ method @androidx.compose.InternalComposeApi public void applyChanges();
+ method @Deprecated public inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+ method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+ method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+ method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+ method @androidx.compose.ComposeCompilerApi public void endDefaults();
+ method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+ method @androidx.compose.ComposeCompilerApi public void endNode();
+ method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+ method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+ method public androidx.compose.Applier<N> getApplier();
+ method public int getCurrentCompoundKeyHash();
+ method public boolean getDefaultsInvalid();
+ method public boolean getInserting();
+ method public androidx.compose.Recomposer getRecomposer();
+ method public boolean getSkipping();
+ method public androidx.compose.SlotTable getSlotTable();
+ method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+ method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+ method @androidx.compose.InternalComposeApi public boolean recompose();
+ method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+ method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+ method @androidx.compose.ComposeCompilerApi public void startDefaults();
+ method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+ method @androidx.compose.ComposeCompilerApi public void startNode();
+ method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public N! useNode();
property public final int currentCompoundKeyHash;
property public final boolean defaultsInvalid;
property public final boolean inserting;
@@ -151,20 +135,11 @@
}
public final class ComposerKt {
- method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static androidx.compose.Composer<?> getComposer();
method public static androidx.compose.Composer<?> getCurrentComposer();
}
- public final class ComposerUpdater<N, T extends N> {
- ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
- method public androidx.compose.Composer<N> getComposer();
- method public T! getNode();
- method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- }
-
@Deprecated public interface ComposerValidator {
method @Deprecated public boolean changed(int value);
method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
- public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+ public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
ctor public CompositionCoroutineScope();
method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
}
- public interface CompositionFrameClock {
+ @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionFrameClockKt {
method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
- method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionKt {
- method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
}
public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
}
+ public final class EmitKt {
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+ }
+
public final class ExpectKt {
}
@@ -241,7 +221,7 @@
method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
method public void nextFrame();
method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
- field public static final androidx.compose.FrameManager! INSTANCE;
+ field public static final androidx.compose.FrameManager INSTANCE;
}
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
}
- public final class NullCompilationScope {
- method public kotlin.Unit getComposer();
+ @Deprecated public final class NullCompilationScope {
+ method @Deprecated public kotlin.Unit getComposer();
property public final kotlin.Unit composer;
- field public static final androidx.compose.NullCompilationScope! INSTANCE;
+ field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
}
public final class ObserveKt {
@@ -316,7 +296,7 @@
method public void removeValue(V value);
}
- @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+ @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
}
@@ -332,12 +312,12 @@
public final class Recomposer {
ctor public Recomposer();
method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public androidx.compose.CompositionFrameClock getFrameClock();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
method public boolean hasPendingChanges();
- method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
- property public final androidx.compose.CompositionFrameClock frameClock;
- field public static final androidx.compose.Recomposer.Companion! Companion;
+ method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.Recomposer.Companion Companion;
}
public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
}
public final class RecomposerKt {
- method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
}
public final class RememberKt {
@@ -430,7 +410,7 @@
method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
property public final int size;
- field public static final androidx.compose.SlotTable.Companion! Companion;
+ field public static final androidx.compose.SlotTable.Companion Companion;
}
@androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
method public abstract Class<?>[] types();
}
- @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ }
+
+ public final class Updater<T> {
+ ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+ method public androidx.compose.Composer<?> getComposer();
+ method public T! getNode();
+ method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+ method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+ method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
}
}
@@ -661,8 +652,8 @@
package androidx.compose.internal {
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
- ctor public RestartableFunction(int key, boolean tracked);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+ ctor public ComposableLambda(int key, boolean tracked);
method public int getKey();
method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
method public void update(Object block);
}
- public final class RestartableFunctionKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+ public final class ComposableLambdaKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
}
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
- ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+ ctor public ComposableLambdaN(int key, boolean tracked, int arity);
method public int getArity();
method public int getKey();
method public R! invoke(java.lang.Object?... args);
method public void update(Object block);
}
- public final class RestartableFunctionNKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+ public final class ComposableLambdaNKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
}
}
diff --git a/compose/compose-runtime/api/public_plus_experimental_current.txt b/compose/compose-runtime/api/public_plus_experimental_current.txt
index ea8ec62b..ba02a6e 100644
--- a/compose/compose-runtime/api/public_plus_experimental_current.txt
+++ b/compose/compose-runtime/api/public_plus_experimental_current.txt
@@ -1,13 +1,26 @@
// Signature format: 3.0
package androidx.compose {
+ @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+ ctor public AbstractApplier(T! root);
+ method public void down(T? node);
+ method public T! getCurrent();
+ method public final T! getRoot();
+ method protected final void move(java.util.List<T>, int from, int to, int count);
+ method protected final void remove(java.util.List<T>, int index, int count);
+ method public void reset();
+ method public void setCurrent(T! p);
+ method public void up();
+ property public T! current;
+ }
+
public final class ActualAndroidKt {
}
public final class ActualJvmKt {
}
- @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+ @androidx.compose.Stable public abstract sealed class Ambient<T> {
method public final inline T! getCurrent();
property public final inline T! current;
}
@@ -25,29 +38,7 @@
property public final boolean valid;
}
- public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
- ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
- method public android.view.Choreographer getChoreographer();
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- }
-
- public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
- method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
- method public android.view.Choreographer getChoreographer();
- method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
- property public final androidx.compose.CompositionFrameClock compositionFrameClock;
- field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
- }
-
- public static final class AndroidUiDispatcher.Companion {
- method public androidx.compose.AndroidUiDispatcher getCurrentThread();
- method public androidx.compose.AndroidUiDispatcher getMain();
- property public final androidx.compose.AndroidUiDispatcher CurrentThread;
- property public final androidx.compose.AndroidUiDispatcher Main;
- }
-
- @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
- ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+ @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
method public void down(N? node);
method public N! getCurrent();
method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
method public void remove(int index, int count);
method public void reset();
method public void up();
- property public final N! current;
- }
-
- @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
- method public void end(N?, N? instance, N? parent);
- method public void insertAt(N?, int index, N? instance);
- method public void move(N?, int from, int to, int count);
- method public void removeAt(N?, int index, int count);
- method public void start(N?, N? instance);
+ property public abstract N! current;
}
public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
}
- @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
+ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
}
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
method public abstract boolean readonly() default false;
method public abstract boolean restartable() default true;
+ method public abstract boolean tracked() default true;
}
@kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,46 +88,46 @@
method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
}
- public class Composer<N> {
+ public final class Composer<N> {
ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
- method @androidx.compose.InternalComposeApi public final void applyChanges();
- method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
- method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
- method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
- method @androidx.compose.ComposeCompilerApi public final void endDefaults();
- method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
- method @androidx.compose.ComposeCompilerApi public final void endNode();
- method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
- method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
- method public final int getCurrentCompoundKeyHash();
- method public final boolean getDefaultsInvalid();
- method public final boolean getInserting();
- method public final androidx.compose.Recomposer getRecomposer();
- method public final boolean getSkipping();
- method public final androidx.compose.SlotTable getSlotTable();
- method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
- method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
- method @androidx.compose.InternalComposeApi public final boolean recompose();
- method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
- method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
- method @androidx.compose.ComposeCompilerApi public final void startDefaults();
- method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
- method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
- method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final N! useNode();
+ method @androidx.compose.InternalComposeApi public void applyChanges();
+ method @Deprecated public inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+ method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+ method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+ method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+ method @androidx.compose.ComposeCompilerApi public void endDefaults();
+ method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+ method @androidx.compose.ComposeCompilerApi public void endNode();
+ method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+ method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+ method public androidx.compose.Applier<N> getApplier();
+ method public int getCurrentCompoundKeyHash();
+ method public boolean getDefaultsInvalid();
+ method public boolean getInserting();
+ method public androidx.compose.Recomposer getRecomposer();
+ method public boolean getSkipping();
+ method public androidx.compose.SlotTable getSlotTable();
+ method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+ method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+ method @androidx.compose.InternalComposeApi public boolean recompose();
+ method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+ method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+ method @androidx.compose.ComposeCompilerApi public void startDefaults();
+ method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+ method @androidx.compose.ComposeCompilerApi public void startNode();
+ method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public N! useNode();
property public final int currentCompoundKeyHash;
property public final boolean defaultsInvalid;
property public final boolean inserting;
@@ -151,20 +135,11 @@
}
public final class ComposerKt {
- method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static androidx.compose.Composer<?> getComposer();
method public static androidx.compose.Composer<?> getCurrentComposer();
}
- public final class ComposerUpdater<N, T extends N> {
- ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
- method public androidx.compose.Composer<N> getComposer();
- method public T! getNode();
- method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- }
-
@Deprecated public interface ComposerValidator {
method @Deprecated public boolean changed(int value);
method @Deprecated public <T> boolean changed(T? value);
@@ -175,26 +150,26 @@
method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
- public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+ public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
ctor public CompositionCoroutineScope();
method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
}
- public interface CompositionFrameClock {
+ @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionFrameClockKt {
method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
- method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionKt {
- method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
}
public interface CompositionLifecycleObserver {
@@ -223,6 +198,11 @@
method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
}
+ public final class EmitKt {
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+ }
+
public final class ExpectKt {
}
@@ -241,7 +221,7 @@
method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
method public void nextFrame();
method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
- field public static final androidx.compose.FrameManager! INSTANCE;
+ field public static final androidx.compose.FrameManager INSTANCE;
}
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -293,10 +273,10 @@
method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
}
- public final class NullCompilationScope {
- method public kotlin.Unit getComposer();
+ @Deprecated public final class NullCompilationScope {
+ method @Deprecated public kotlin.Unit getComposer();
property public final kotlin.Unit composer;
- field public static final androidx.compose.NullCompilationScope! INSTANCE;
+ field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
}
public final class ObserveKt {
@@ -316,7 +296,7 @@
method public void removeValue(V value);
}
- @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+ @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
}
@@ -332,12 +312,12 @@
public final class Recomposer {
ctor public Recomposer();
method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public androidx.compose.CompositionFrameClock getFrameClock();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
method public boolean hasPendingChanges();
- method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
- property public final androidx.compose.CompositionFrameClock frameClock;
- field public static final androidx.compose.Recomposer.Companion! Companion;
+ method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.Recomposer.Companion Companion;
}
public static final class Recomposer.Companion {
@@ -346,7 +326,7 @@
}
public final class RecomposerKt {
- method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
}
public final class RememberKt {
@@ -430,7 +410,7 @@
method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
property public final int size;
- field public static final androidx.compose.SlotTable.Companion! Companion;
+ field public static final androidx.compose.SlotTable.Companion Companion;
}
@androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -522,7 +502,18 @@
method public abstract Class<?>[] types();
}
- @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ }
+
+ public final class Updater<T> {
+ ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+ method public androidx.compose.Composer<?> getComposer();
+ method public T! getNode();
+ method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+ method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+ method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
}
}
@@ -661,8 +652,8 @@
package androidx.compose.internal {
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
- ctor public RestartableFunction(int key, boolean tracked);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+ ctor public ComposableLambda(int key, boolean tracked);
method public int getKey();
method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -686,22 +677,22 @@
method public void update(Object block);
}
- public final class RestartableFunctionKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+ public final class ComposableLambdaKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
}
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
- ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+ ctor public ComposableLambdaN(int key, boolean tracked, int arity);
method public int getArity();
method public int getKey();
method public R! invoke(java.lang.Object?... args);
method public void update(Object block);
}
- public final class RestartableFunctionNKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+ public final class ComposableLambdaNKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
}
}
diff --git a/compose/compose-runtime/api/restricted_0.1.0-dev15.txt b/compose/compose-runtime/api/restricted_0.1.0-dev15.txt
index b097892..aa94c38 100644
--- a/compose/compose-runtime/api/restricted_0.1.0-dev15.txt
+++ b/compose/compose-runtime/api/restricted_0.1.0-dev15.txt
@@ -1,13 +1,26 @@
// Signature format: 3.0
package androidx.compose {
+ @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+ ctor public AbstractApplier(T! root);
+ method public void down(T? node);
+ method public T! getCurrent();
+ method public final T! getRoot();
+ method protected final void move(java.util.List<T>, int from, int to, int count);
+ method protected final void remove(java.util.List<T>, int index, int count);
+ method public void reset();
+ method public void setCurrent(T! p);
+ method public void up();
+ property public T! current;
+ }
+
public final class ActualAndroidKt {
}
public final class ActualJvmKt {
}
- @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+ @androidx.compose.Stable public abstract sealed class Ambient<T> {
method public final inline T! getCurrent();
property public final inline T! current;
}
@@ -25,29 +38,7 @@
property public final boolean valid;
}
- public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
- ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
- method public android.view.Choreographer getChoreographer();
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- }
-
- public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
- method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
- method public android.view.Choreographer getChoreographer();
- method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
- property public final androidx.compose.CompositionFrameClock compositionFrameClock;
- field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
- }
-
- public static final class AndroidUiDispatcher.Companion {
- method public androidx.compose.AndroidUiDispatcher getCurrentThread();
- method public androidx.compose.AndroidUiDispatcher getMain();
- property public final androidx.compose.AndroidUiDispatcher CurrentThread;
- property public final androidx.compose.AndroidUiDispatcher Main;
- }
-
- @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
- ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+ @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
method public void down(N? node);
method public N! getCurrent();
method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
method public void remove(int index, int count);
method public void reset();
method public void up();
- property public final N! current;
- }
-
- @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
- method public void end(N?, N? instance, N? parent);
- method public void insertAt(N?, int index, N? instance);
- method public void move(N?, int from, int to, int count);
- method public void removeAt(N?, int index, int count);
- method public void start(N?, N? instance);
+ property public abstract N! current;
}
public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
}
- @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
+ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
}
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
method public abstract boolean readonly() default false;
method public abstract boolean restartable() default true;
+ method public abstract boolean tracked() default true;
}
@kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,48 +88,48 @@
method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
}
- public class Composer<N> {
+ public final class Composer<N> {
ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
- method @androidx.compose.InternalComposeApi public final void applyChanges();
- method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
- method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
- method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @kotlin.PublishedApi internal final <T> T! consume(androidx.compose.Ambient<T> key);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
- method @androidx.compose.ComposeCompilerApi public final void endDefaults();
- method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
- method @androidx.compose.ComposeCompilerApi public final void endNode();
- method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
- method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
- method public final int getCurrentCompoundKeyHash();
- method public final boolean getDefaultsInvalid();
- method public final boolean getInserting();
- method public final androidx.compose.Recomposer getRecomposer();
- method public final boolean getSkipping();
- method public final androidx.compose.SlotTable getSlotTable();
- method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
- method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
- method @androidx.compose.InternalComposeApi public final boolean recompose();
- method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
- method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
- method @androidx.compose.ComposeCompilerApi public final void startDefaults();
- method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
- method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
- method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
- method @kotlin.PublishedApi internal final void updateValue(Object? value);
- method @androidx.compose.ComposeCompilerApi public final N! useNode();
+ method @androidx.compose.InternalComposeApi public void applyChanges();
+ method @Deprecated public inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+ method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+ method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @kotlin.PublishedApi internal <T> T! consume(androidx.compose.Ambient<T> key);
+ method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+ method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+ method @androidx.compose.ComposeCompilerApi public void endDefaults();
+ method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+ method @androidx.compose.ComposeCompilerApi public void endNode();
+ method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+ method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+ method public androidx.compose.Applier<N> getApplier();
+ method public int getCurrentCompoundKeyHash();
+ method public boolean getDefaultsInvalid();
+ method public boolean getInserting();
+ method public androidx.compose.Recomposer getRecomposer();
+ method public boolean getSkipping();
+ method public androidx.compose.SlotTable getSlotTable();
+ method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+ method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+ method @androidx.compose.InternalComposeApi public boolean recompose();
+ method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+ method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+ method @androidx.compose.ComposeCompilerApi public void startDefaults();
+ method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+ method @androidx.compose.ComposeCompilerApi public void startNode();
+ method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+ method @kotlin.PublishedApi internal void updateValue(Object? value);
+ method @androidx.compose.ComposeCompilerApi public N! useNode();
property public final int currentCompoundKeyHash;
property public final boolean defaultsInvalid;
property public final boolean inserting;
@@ -154,7 +138,8 @@
public final class ComposerKt {
method @kotlin.PublishedApi internal static inline <N, T> T! cache(androidx.compose.Composer<N>, boolean valid = true, kotlin.jvm.functions.Function0<? extends T> block);
- method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static androidx.compose.Composer<?> getComposer();
method public static androidx.compose.Composer<?> getCurrentComposer();
field @kotlin.PublishedApi internal static final androidx.compose.OpaqueKey ambientMap;
field @kotlin.PublishedApi internal static final int ambientMapKey = 202; // 0xca
@@ -170,16 +155,6 @@
field @kotlin.PublishedApi internal static final int referenceKey = 206; // 0xce
}
- public final class ComposerUpdater<N, T extends N> {
- ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
- method public androidx.compose.Composer<N> getComposer();
- method public T! getNode();
- method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- }
-
@Deprecated public interface ComposerValidator {
method @Deprecated public boolean changed(int value);
method @Deprecated public <T> boolean changed(T? value);
@@ -190,26 +165,26 @@
method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
- public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+ public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
ctor public CompositionCoroutineScope();
method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
}
- public interface CompositionFrameClock {
+ @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionFrameClockKt {
method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
- method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionKt {
- method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
}
public interface CompositionLifecycleObserver {
@@ -238,6 +213,11 @@
method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
}
+ public final class EmitKt {
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+ }
+
public final class ExpectKt {
}
@@ -256,7 +236,7 @@
method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
method public void nextFrame();
method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
- field public static final androidx.compose.FrameManager! INSTANCE;
+ field public static final androidx.compose.FrameManager INSTANCE;
}
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -308,10 +288,10 @@
method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
}
- public final class NullCompilationScope {
- method public kotlin.Unit getComposer();
+ @Deprecated public final class NullCompilationScope {
+ method @Deprecated public kotlin.Unit getComposer();
property public final kotlin.Unit composer;
- field public static final androidx.compose.NullCompilationScope! INSTANCE;
+ field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
}
public final class ObserveKt {
@@ -346,7 +326,7 @@
method public void onLeave();
}
- @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+ @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
}
@@ -362,12 +342,12 @@
public final class Recomposer {
ctor public Recomposer();
method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public androidx.compose.CompositionFrameClock getFrameClock();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
method public boolean hasPendingChanges();
- method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
- property public final androidx.compose.CompositionFrameClock frameClock;
- field public static final androidx.compose.Recomposer.Companion! Companion;
+ method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.Recomposer.Companion Companion;
}
public static final class Recomposer.Companion {
@@ -376,7 +356,7 @@
}
public final class RecomposerKt {
- method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
}
public final class RememberKt {
@@ -460,7 +440,7 @@
method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
property public final int size;
- field public static final androidx.compose.SlotTable.Companion! Companion;
+ field public static final androidx.compose.SlotTable.Companion Companion;
}
@androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -553,7 +533,18 @@
method public abstract Class<?>[] types();
}
- @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ }
+
+ public final class Updater<T> {
+ ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+ method public androidx.compose.Composer<?> getComposer();
+ method public T! getNode();
+ method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+ method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+ method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
}
}
@@ -693,8 +684,8 @@
package androidx.compose.internal {
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
- ctor public RestartableFunction(int key, boolean tracked);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+ ctor public ComposableLambda(int key, boolean tracked);
method public int getKey();
method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -718,22 +709,22 @@
method public void update(Object block);
}
- public final class RestartableFunctionKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+ public final class ComposableLambdaKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
}
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
- ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+ ctor public ComposableLambdaN(int key, boolean tracked, int arity);
method public int getArity();
method public int getKey();
method public R! invoke(java.lang.Object?... args);
method public void update(Object block);
}
- public final class RestartableFunctionNKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+ public final class ComposableLambdaNKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
}
}
diff --git a/compose/compose-runtime/api/restricted_current.txt b/compose/compose-runtime/api/restricted_current.txt
index b097892..aa94c38 100644
--- a/compose/compose-runtime/api/restricted_current.txt
+++ b/compose/compose-runtime/api/restricted_current.txt
@@ -1,13 +1,26 @@
// Signature format: 3.0
package androidx.compose {
+ @androidx.compose.ExperimentalComposeApi public abstract class AbstractApplier<T> implements androidx.compose.Applier<T> {
+ ctor public AbstractApplier(T! root);
+ method public void down(T? node);
+ method public T! getCurrent();
+ method public final T! getRoot();
+ method protected final void move(java.util.List<T>, int from, int to, int count);
+ method protected final void remove(java.util.List<T>, int index, int count);
+ method public void reset();
+ method public void setCurrent(T! p);
+ method public void up();
+ property public T! current;
+ }
+
public final class ActualAndroidKt {
}
public final class ActualJvmKt {
}
- @androidx.compose.Immutable public abstract sealed class Ambient<T> {
+ @androidx.compose.Stable public abstract sealed class Ambient<T> {
method public final inline T! getCurrent();
property public final inline T! current;
}
@@ -25,29 +38,7 @@
property public final boolean valid;
}
- public final class AndroidUiCompositionFrameClock implements androidx.compose.CompositionFrameClock {
- ctor public AndroidUiCompositionFrameClock(android.view.Choreographer choreographer);
- method public android.view.Choreographer getChoreographer();
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- }
-
- public final class AndroidUiDispatcher extends kotlinx.coroutines.CoroutineDispatcher {
- method public void dispatch(kotlin.coroutines.CoroutineContext context, Runnable block);
- method public android.view.Choreographer getChoreographer();
- method public androidx.compose.CompositionFrameClock getCompositionFrameClock();
- property public final androidx.compose.CompositionFrameClock compositionFrameClock;
- field public static final androidx.compose.AndroidUiDispatcher.Companion! Companion;
- }
-
- public static final class AndroidUiDispatcher.Companion {
- method public androidx.compose.AndroidUiDispatcher getCurrentThread();
- method public androidx.compose.AndroidUiDispatcher getMain();
- property public final androidx.compose.AndroidUiDispatcher CurrentThread;
- property public final androidx.compose.AndroidUiDispatcher Main;
- }
-
- @androidx.compose.ExperimentalComposeApi public final class Applier<N> {
- ctor public Applier(N! root, androidx.compose.ApplyAdapter<N> adapter);
+ @androidx.compose.ExperimentalComposeApi public interface Applier<N> {
method public void down(N? node);
method public N! getCurrent();
method public void insert(int index, N? instance);
@@ -55,15 +46,7 @@
method public void remove(int index, int count);
method public void reset();
method public void up();
- property public final N! current;
- }
-
- @androidx.compose.ExperimentalComposeApi public interface ApplyAdapter<N> {
- method public void end(N?, N? instance, N? parent);
- method public void insertAt(N?, int index, N? instance);
- method public void move(N?, int from, int to, int count);
- method public void removeAt(N?, int index, int count);
- method public void start(N?, N? instance);
+ property public abstract N! current;
}
public final class BitwiseOperatorsKt {
@@ -88,12 +71,13 @@
method public void onDispose(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
}
- @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
+ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.PROPERTY}) public @interface Composable {
}
@kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface ComposableContract {
method public abstract boolean readonly() default false;
method public abstract boolean restartable() default true;
+ method public abstract boolean tracked() default true;
}
@kotlin.RequiresOptIn(level=RequiresOptIn.Level.WARNING, message="This API is intended to be targeted by the Compose Compiler Plugin and not called " + "directly.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.TYPEALIAS}) public @interface ComposeCompilerApi {
@@ -104,48 +88,48 @@
method public static inline kotlin.jvm.functions.Function0<kotlin.Unit> orEmpty(kotlin.jvm.functions.Function0<kotlin.Unit>?);
}
- public class Composer<N> {
+ public final class Composer<N> {
ctor public Composer(androidx.compose.SlotTable slotTable, androidx.compose.Applier<N> applier, androidx.compose.Recomposer recomposer);
- method @androidx.compose.InternalComposeApi public final void applyChanges();
- method @Deprecated public final inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(Object? value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(char value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(byte value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(short value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(boolean value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(float value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(long value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(double value);
- method @androidx.compose.ComposeCompilerApi public final boolean changed(int value);
- method @androidx.compose.InternalComposeApi public final void collectKeySourceInformation();
- method protected final void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
- method @kotlin.PublishedApi internal final <T> T! consume(androidx.compose.Ambient<T> key);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final <T extends N> void emitNode(kotlin.jvm.functions.Function0<? extends T> factory);
- method @androidx.compose.ComposeCompilerApi public final void emitNode(N? node);
- method @androidx.compose.ComposeCompilerApi public final void endDefaults();
- method @androidx.compose.ComposeCompilerApi public final void endMovableGroup();
- method @androidx.compose.ComposeCompilerApi public final void endNode();
- method @androidx.compose.ComposeCompilerApi public final void endReplaceableGroup();
- method @androidx.compose.ComposeCompilerApi public final androidx.compose.ScopeUpdateScope? endRestartGroup();
- method public final int getCurrentCompoundKeyHash();
- method public final boolean getDefaultsInvalid();
- method public final boolean getInserting();
- method public final androidx.compose.Recomposer getRecomposer();
- method public final boolean getSkipping();
- method public final androidx.compose.SlotTable getSlotTable();
- method @androidx.compose.ComposeCompilerApi public final Object joinKey(Object? left, Object? right);
- method @androidx.compose.ComposeCompilerApi public final Object? nextSlot();
- method @androidx.compose.InternalComposeApi public final boolean recompose();
- method @androidx.compose.ComposeCompilerApi public final void skipCurrentGroup();
- method @androidx.compose.ComposeCompilerApi public final void skipToGroupEnd();
- method @androidx.compose.ComposeCompilerApi public final void startDefaults();
- method @androidx.compose.ComposeCompilerApi public final void startMovableGroup(int key, Object? dataKey);
- method @androidx.compose.ComposeCompilerApi public final void startNode(Object key);
- method @androidx.compose.ComposeCompilerApi public final void startReplaceableGroup(int key);
- method @androidx.compose.ComposeCompilerApi public final void startRestartGroup(int key);
- method @kotlin.PublishedApi internal final void updateValue(Object? value);
- method @androidx.compose.ComposeCompilerApi public final N! useNode();
+ method @androidx.compose.InternalComposeApi public void applyChanges();
+ method @Deprecated public inline void call(Object key, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerValidator,java.lang.Boolean> invalid, kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(Object? value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(char value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(byte value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(short value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(boolean value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(float value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(long value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(double value);
+ method @androidx.compose.ComposeCompilerApi public boolean changed(int value);
+ method @androidx.compose.InternalComposeApi public void collectKeySourceInformation();
+ method @androidx.compose.InternalComposeApi public void composeRoot(kotlin.jvm.functions.Function0<kotlin.Unit> block);
+ method @kotlin.PublishedApi internal <T> T! consume(androidx.compose.Ambient<T> key);
+ method @androidx.compose.ComposeCompilerApi public <T extends N> void createNode(kotlin.jvm.functions.Function0<? extends T> factory);
+ method @androidx.compose.ComposeCompilerApi public void emitNode(Object node);
+ method @androidx.compose.ComposeCompilerApi public void endDefaults();
+ method @androidx.compose.ComposeCompilerApi public void endMovableGroup();
+ method @androidx.compose.ComposeCompilerApi public void endNode();
+ method @androidx.compose.ComposeCompilerApi public void endReplaceableGroup();
+ method @androidx.compose.ComposeCompilerApi public androidx.compose.ScopeUpdateScope? endRestartGroup();
+ method public androidx.compose.Applier<N> getApplier();
+ method public int getCurrentCompoundKeyHash();
+ method public boolean getDefaultsInvalid();
+ method public boolean getInserting();
+ method public androidx.compose.Recomposer getRecomposer();
+ method public boolean getSkipping();
+ method public androidx.compose.SlotTable getSlotTable();
+ method @androidx.compose.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
+ method @androidx.compose.ComposeCompilerApi public Object? nextSlot();
+ method @androidx.compose.InternalComposeApi public boolean recompose();
+ method @androidx.compose.ComposeCompilerApi public void skipCurrentGroup();
+ method @androidx.compose.ComposeCompilerApi public void skipToGroupEnd();
+ method @androidx.compose.ComposeCompilerApi public void startDefaults();
+ method @androidx.compose.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
+ method @androidx.compose.ComposeCompilerApi public void startNode();
+ method @androidx.compose.ComposeCompilerApi public void startReplaceableGroup(int key);
+ method @androidx.compose.ComposeCompilerApi public void startRestartGroup(int key);
+ method @kotlin.PublishedApi internal void updateValue(Object? value);
+ method @androidx.compose.ComposeCompilerApi public N! useNode();
property public final int currentCompoundKeyHash;
property public final boolean defaultsInvalid;
property public final boolean inserting;
@@ -154,7 +138,8 @@
public final class ComposerKt {
method @kotlin.PublishedApi internal static inline <N, T> T! cache(androidx.compose.Composer<N>, boolean valid = true, kotlin.jvm.functions.Function0<? extends T> block);
- method public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static inline <T> T! escapeCompose(kotlin.jvm.functions.Function1<? super androidx.compose.NullCompilationScope,? extends T> block);
+ method @Deprecated public static androidx.compose.Composer<?> getComposer();
method public static androidx.compose.Composer<?> getCurrentComposer();
field @kotlin.PublishedApi internal static final androidx.compose.OpaqueKey ambientMap;
field @kotlin.PublishedApi internal static final int ambientMapKey = 202; // 0xca
@@ -170,16 +155,6 @@
field @kotlin.PublishedApi internal static final int referenceKey = 206; // 0xce
}
- public final class ComposerUpdater<N, T extends N> {
- ctor public ComposerUpdater(androidx.compose.Composer<N> composer, T! node);
- method public androidx.compose.Composer<N> getComposer();
- method public T! getNode();
- method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
- method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
- }
-
@Deprecated public interface ComposerValidator {
method @Deprecated public boolean changed(int value);
method @Deprecated public <T> boolean changed(T? value);
@@ -190,26 +165,26 @@
method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
- public abstract class CompositionCoroutineScope implements androidx.compose.CompositionFrameClock kotlinx.coroutines.CoroutineScope {
+ public abstract class CompositionCoroutineScope implements kotlinx.coroutines.CoroutineScope androidx.compose.dispatch.MonotonicFrameClock {
ctor public CompositionCoroutineScope();
method @Deprecated public final suspend Object? awaitFrame(kotlin.coroutines.Continuation<? super java.lang.Long> p);
}
- public interface CompositionFrameClock {
+ @Deprecated public interface CompositionFrameClock extends androidx.compose.dispatch.MonotonicFrameClock {
method @Deprecated public default suspend <R> Object? awaitFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
- method public suspend <R> Object? withFrameNanos(kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionFrameClockKt {
method @Deprecated public static suspend inline <R> Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
method @Deprecated public static suspend Object? awaitFrameMillis(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
method @Deprecated public static suspend Object? awaitFrameNanos(androidx.compose.CompositionFrameClock, kotlin.coroutines.Continuation<? super java.lang.Long> p);
- method public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
+ method @Deprecated public static suspend inline <R> Object? withFrameMillis(androidx.compose.CompositionFrameClock, kotlin.jvm.functions.Function1<? super java.lang.Long,? extends R> onFrame, kotlin.coroutines.Continuation<? super R> p);
}
public final class CompositionKt {
- method public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
method @Deprecated public static androidx.compose.Composition compositionFor(Object container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function2<? super androidx.compose.SlotTable,? super androidx.compose.Recomposer,? extends androidx.compose.Composer<?>> composerFactory);
+ method @androidx.compose.ExperimentalComposeApi public static androidx.compose.Composition compositionFor(Object key, androidx.compose.Applier<?> applier, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> onCreated = {});
}
public interface CompositionLifecycleObserver {
@@ -238,6 +213,11 @@
method @androidx.compose.Composable public static void onPreCommit(Object![]? inputs, kotlin.jvm.functions.Function1<? super androidx.compose.CommitScope,kotlin.Unit> callback);
}
+ public final class EmitKt {
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update);
+ method @androidx.compose.Composable public static inline <T extends java.lang.Object, reified E extends androidx.compose.Applier<?>> void emit(kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.Updater<T>,? extends kotlin.Unit> update, kotlin.jvm.functions.Function0<? extends kotlin.Unit> children);
+ }
+
public final class ExpectKt {
}
@@ -256,7 +236,7 @@
method @org.jetbrains.annotations.TestOnly public <T> T! isolated(kotlin.jvm.functions.Function0<? extends T> block);
method public void nextFrame();
method @org.jetbrains.annotations.TestOnly public <T> T! unframed(kotlin.jvm.functions.Function0<? extends T> block);
- field public static final androidx.compose.FrameManager! INSTANCE;
+ field public static final androidx.compose.FrameManager INSTANCE;
}
@androidx.compose.StableMarker @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.CLASS) public @interface Immutable {
@@ -308,10 +288,10 @@
method @androidx.compose.Composable public static inline <T, reified V1, reified V2> androidx.compose.MutableState<T>! stateFor(V1? v1, V2? v2, kotlin.jvm.functions.Function0<? extends T> init);
}
- public final class NullCompilationScope {
- method public kotlin.Unit getComposer();
+ @Deprecated public final class NullCompilationScope {
+ method @Deprecated public kotlin.Unit getComposer();
property public final kotlin.Unit composer;
- field public static final androidx.compose.NullCompilationScope! INSTANCE;
+ field @Deprecated public static final androidx.compose.NullCompilationScope INSTANCE;
}
public final class ObserveKt {
@@ -346,7 +326,7 @@
method public void onLeave();
}
- @androidx.compose.Immutable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
+ @androidx.compose.Stable public abstract class ProvidableAmbient<T> extends androidx.compose.Ambient<T> {
method public final infix androidx.compose.ProvidedValue<T> provides(T? value);
}
@@ -362,12 +342,12 @@
public final class Recomposer {
ctor public Recomposer();
method public suspend Object? awaitIdle(kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public androidx.compose.CompositionFrameClock getFrameClock();
+ method public androidx.compose.dispatch.MonotonicFrameClock getFrameClock();
method public boolean hasPendingChanges();
- method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.CompositionFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
- method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.CompositionFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
- property public final androidx.compose.CompositionFrameClock frameClock;
- field public static final androidx.compose.Recomposer.Companion! Companion;
+ method public suspend Object? recomposeAndApplyChanges(kotlinx.coroutines.CoroutineScope applyCoroutineScope, androidx.compose.dispatch.MonotonicFrameClock frameClock, long frameCount, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public suspend Object? runRecomposeAndApplyChanges(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.coroutines.Continuation<?> p);
+ property public final androidx.compose.dispatch.MonotonicFrameClock frameClock;
+ field public static final androidx.compose.Recomposer.Companion Companion;
}
public static final class Recomposer.Companion {
@@ -376,7 +356,7 @@
}
public final class RecomposerKt {
- method public static suspend Object? withRunningRecomposer(androidx.compose.CompositionFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public static suspend Object? withRunningRecomposer(androidx.compose.dispatch.MonotonicFrameClock frameClock, kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.Recomposer,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
}
public final class RememberKt {
@@ -460,7 +440,7 @@
method @androidx.compose.InternalComposeApi @org.jetbrains.annotations.TestOnly public void verifyWellFormed();
method @androidx.compose.InternalComposeApi public <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.SlotWriter,? extends T> block);
property public final int size;
- field public static final androidx.compose.SlotTable.Companion! Companion;
+ field public static final androidx.compose.SlotTable.Companion Companion;
}
@androidx.compose.InternalComposeApi public static final class SlotTable.Companion {
@@ -553,7 +533,18 @@
method public abstract Class<?>[] types();
}
- @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ @Deprecated @androidx.compose.ExperimentalComposeApi @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=AnnotationTarget.FUNCTION) public @interface Untracked {
+ }
+
+ public final class Updater<T> {
+ ctor public Updater(androidx.compose.Composer<?> composer, T! node);
+ method public androidx.compose.Composer<?> getComposer();
+ method public T! getNode();
+ method public inline void reconcile(kotlin.jvm.functions.Function1<? super T,kotlin.Unit> block);
+ method public inline void set(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void set(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
+ method public inline void update(int value, kotlin.jvm.functions.Function2<? super T,? super java.lang.Integer,kotlin.Unit> block);
+ method public inline <reified V> void update(V? value, kotlin.jvm.functions.Function2<? super T,? super V,? extends kotlin.Unit> block);
}
}
@@ -693,8 +684,8 @@
package androidx.compose.internal {
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
- ctor public RestartableFunction(int key, boolean tracked);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> implements kotlin.jvm.functions.Function10<P1,P2,P3,P4,P5,P6,P7,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function11<P1,P2,P3,P4,P5,P6,P7,P8,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function12<P1,P2,P3,P4,P5,P6,P7,P8,P9,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function13<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function14<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function15<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function16<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function17<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function18<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function20<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function21<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function22<P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function3<androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function4<P1,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function5<P1,P2,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function6<P1,P2,P3,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function7<P1,P2,P3,P4,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function8<P1,P2,P3,P4,P5,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> kotlin.jvm.functions.Function9<P1,P2,P3,P4,P5,P6,androidx.compose.Composer<?>,java.lang.Integer,java.lang.Integer,R> {
+ ctor public ComposableLambda(int key, boolean tracked);
method public int getKey();
method public operator R! invoke(androidx.compose.Composer<?> c, int k, int changed);
method public operator R! invoke(P1? p1, androidx.compose.Composer<?> c, int k, int changed);
@@ -718,22 +709,22 @@
method public void update(Object block);
}
- public final class RestartableFunctionKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunction(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunction<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> restartableFunctionInstance(int key, boolean tracked, Object block);
+ public final class ComposableLambdaKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambda(androidx.compose.Composer<?> composer, int key, boolean tracked, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambda<java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object> composableLambdaInstance(int key, boolean tracked, Object block);
}
- @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class RestartableFunctionN<R> implements kotlin.jvm.functions.FunctionN<R> {
- ctor public RestartableFunctionN(int key, boolean tracked, int arity);
+ @androidx.compose.ComposeCompilerApi @androidx.compose.Stable public final class ComposableLambdaN<R> implements kotlin.jvm.functions.FunctionN<R> {
+ ctor public ComposableLambdaN(int key, boolean tracked, int arity);
method public int getArity();
method public int getKey();
method public R! invoke(java.lang.Object?... args);
method public void update(Object block);
}
- public final class RestartableFunctionNKt {
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
- method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.RestartableFunctionN<?> restartableFunctionNInstance(int key, boolean tracked, int arity, Object block);
+ public final class ComposableLambdaNKt {
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaN(androidx.compose.Composer<?> composer, int key, boolean tracked, int arity, Object block);
+ method @androidx.compose.ComposeCompilerApi public static androidx.compose.internal.ComposableLambdaN<?> composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
}
}
diff --git a/compose/compose-runtime/build.gradle b/compose/compose-runtime/build.gradle
index 6d0d947..3b3989b 100644
--- a/compose/compose-runtime/build.gradle
+++ b/compose/compose-runtime/build.gradle
@@ -39,6 +39,7 @@
commonMain.dependencies {
implementation(KOTLIN_STDLIB_COMMON)
implementation(KOTLIN_COROUTINES_CORE_COMMON)
+ api project(':compose:compose-dispatch')
}
jvmMain.dependencies {
implementation(KOTLIN_STDLIB)
diff --git a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml
index e48051b..2759840 100644
--- a/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml
+++ b/compose/compose-runtime/compose-runtime-benchmark/src/androidTest/AndroidManifest.xml
@@ -26,7 +26,11 @@
android:requestLegacyExternalStorage="true"
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
+
<activity
android:name=".ComposeActivity"/>
</application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/CustomTreeCompositionSamples.kt b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/CustomTreeCompositionSamples.kt
new file mode 100644
index 0000000..32c5959
--- /dev/null
+++ b/compose/compose-runtime/samples/src/main/java/androidx/compose/samples/CustomTreeCompositionSamples.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.AbstractApplier
+import androidx.compose.Composable
+import androidx.compose.Composition
+import androidx.compose.ExperimentalComposeApi
+import androidx.compose.Recomposer
+import androidx.compose.compositionFor
+import androidx.compose.emit
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.compose.state
+
+@Suppress("unused")
+@OptIn(ExperimentalComposeApi::class)
+@Sampled
+fun CustomTreeComposition() {
+ // Provided we have a tree with a node base type like the following
+ abstract class Node {
+ val children = mutableListOf<Node>()
+ }
+
+ // We would implement an Applier class like the following, which would teach compose how to
+ // manage a tree of Nodes.
+ class NodeApplier(root: Node) : AbstractApplier<Node>(root) {
+ override fun insert(index: Int, instance: Node) {
+ current.children.add(index, instance)
+ }
+
+ override fun remove(index: Int, count: Int) {
+ current.children.remove(index, count)
+ }
+
+ override fun move(from: Int, to: Int, count: Int) {
+ current.children.move(from, to, count)
+ }
+ }
+
+ // A function like the following could be created to create a composition provided a root Node.
+ fun Node.setContent(content: @Composable () -> Unit): Composition {
+ return compositionFor(this, NodeApplier(this), Recomposer.current()).also {
+ setContent(content)
+ }
+ }
+
+ // assuming we have Node sub-classes like "TextNode" and "GroupNode"
+ class TextNode : Node() {
+ var text: String = ""
+ var onClick: () -> Unit = {}
+ }
+ class GroupNode : Node()
+
+ // Composable equivalents could be created
+ @Composable fun Text(text: String, onClick: () -> Unit = {}) {
+ emit<TextNode, NodeApplier>(::TextNode) {
+ set(text) { this.text = it }
+ set(onClick) { this.onClick = it }
+ }
+ }
+
+ @Composable fun Group(content: @Composable () -> Unit) {
+ emit<GroupNode, NodeApplier>(::GroupNode, {}, content)
+ }
+
+ // and then a sample tree could be composed:
+ fun runApp(root: GroupNode) {
+ root.setContent {
+ var count by state { 0 }
+ Group {
+ Text("Count: $count")
+ Text("Increment") { count++ }
+ }
+ }
+ }
+}
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt
index d870aa60..0bd4b6a 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/AmbientTests.kt
@@ -19,15 +19,14 @@
import android.widget.TextView
import androidx.compose.Ambient
import androidx.compose.Composable
+import androidx.compose.ComposableContract
import androidx.compose.CompositionReference
import androidx.compose.ExperimentalComposeApi
import androidx.compose.Providers
import androidx.compose.Recomposer
import androidx.compose.StructurallyEqual
-import androidx.compose.Untracked
import androidx.compose.ambientOf
import androidx.compose.compositionReference
-import androidx.compose.escapeCompose
import androidx.compose.invalidate
import androidx.compose.remember
import androidx.compose.staticAmbientOf
@@ -35,7 +34,7 @@
import androidx.test.filters.MediumTest
import androidx.ui.core.LayoutNode
import androidx.ui.core.subcomposeInto
-import androidx.ui.node.UiComposer
+import androidx.ui.viewinterop.emitView
import org.junit.After
import org.junit.Rule
import org.junit.Test
@@ -64,11 +63,9 @@
@RunWith(AndroidJUnit4::class)
class AmbientTests : BaseComposeTest() {
- val composer: UiComposer get() = error("should not be called")
-
@Composable
fun Text(value: String, id: Int = 100) {
- TextView(id = id, text = value)
+ emitView(::TextView) { it.id = id; it.text = value; }
}
@Composable
@@ -511,18 +508,17 @@
}
@Composable fun deferredSubCompose(block: @Composable () -> Unit): () -> Unit {
- val container = remember { escapeCompose { LayoutNode() } }
+ val container = remember { LayoutNode() }
val ref = Ref<CompositionReference>()
narrowInvalidateForReference(ref = ref)
return {
@OptIn(ExperimentalComposeApi::class)
- // TODO(b/150390669): Review use of @Untracked
+ // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
subcomposeInto(
- activityRule.activity,
container,
Recomposer.current(),
ref.value
- ) @Untracked {
+ ) @ComposableContract(tracked = false) {
block()
}
}
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt
index 1a1235e..eb10e2f 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/BaseComposeTest.kt
@@ -27,15 +27,16 @@
import androidx.compose.Choreographer
import androidx.compose.ChoreographerFrameCallback
import androidx.compose.Composable
+import androidx.compose.ComposableContract
import androidx.compose.Composition
import androidx.compose.ExperimentalComposeApi
import androidx.compose.FrameManager
import androidx.compose.Looper
+import androidx.compose.Providers
import androidx.compose.Recomposer
-import androidx.compose.Untracked
import androidx.compose.compositionReference
-import androidx.compose.escapeCompose
import androidx.compose.remember
+import androidx.ui.core.ContextAmbient
import androidx.ui.core.LayoutNode
import androidx.ui.core.setViewContent
import androidx.ui.core.subcomposeInto
@@ -116,37 +117,28 @@
fun compose(
composable: @Composable () -> Unit
- ) = UiTester(
- activity,
- composable
- )
-
- fun composeEmittables(
- composable: @Composable () -> Unit
- ) = EmittableTester(
+ ) = ComposeTester(
activity,
composable
)
@Composable
fun subCompose(block: @Composable () -> Unit) {
- val container =
- remember { escapeCompose { LayoutNode() } }
+ val container = remember { LayoutNode() }
val reference = compositionReference()
- // TODO(b/150390669): Review use of @Untracked
+ // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
@OptIn(ExperimentalComposeApi::class)
subcomposeInto(
- activityRule.activity,
container,
Recomposer.current(),
reference
- ) @Untracked {
+ ) @ComposableContract(tracked = false) {
block()
}
}
}
-sealed class ComposeTester(val activity: Activity, val composable: @Composable () -> Unit) {
+class ComposeTester(val activity: Activity, val composable: @Composable () -> Unit) {
inner class ActiveTest(val activity: Activity, val composition: Composition) {
fun then(block: ActiveTest.(activity: Activity) -> Unit): ActiveTest {
activity.waitForAFrame()
@@ -161,7 +153,15 @@
}
}
- abstract fun initialComposition(composable: @Composable () -> Unit): Composition
+ private fun initialComposition(composable: @Composable () -> Unit): Composition {
+ return activity.show {
+ Providers(
+ ContextAmbient provides activity
+ ) {
+ composable()
+ }
+ }
+ }
fun then(block: ComposeTester.(activity: Activity) -> Unit): ActiveTest {
val composition = initialComposition(composable)
@@ -172,24 +172,3 @@
return ActiveTest(activity, composition)
}
}
-
-class EmittableTester(activity: Activity, composable: @Composable () -> Unit) :
- ComposeTester(activity, composable) {
- override fun initialComposition(composable: @Composable () -> Unit): Composition {
- var composition: Composition? = null
- activity.uiThread {
- FrameManager.nextFrame()
- composition = activity.setEmittableContent(composable)
- }
- return composition!!
- }
-}
-
-class UiTester(activity: Activity, composable: @Composable () -> Unit) :
- ComposeTester(activity, composable) {
- override fun initialComposition(composable: @Composable () -> Unit): Composition {
- return activity.show {
- composable()
- }
- }
-}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt
index ecba4dd..6c22dd6 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeIntoTests.kt
@@ -18,6 +18,8 @@
import android.os.HandlerThread
import androidx.compose.Composable
+import androidx.compose.ComposableContract
+import androidx.compose.ExperimentalComposeApi
import androidx.compose.FrameManager
import androidx.compose.Handler
import androidx.compose.clearRoots
@@ -52,7 +54,8 @@
var initializationCount = 0
var commitCount = 0
- val composable = @Composable {
+ @OptIn(ExperimentalComposeApi::class)
+ val composable = @Composable @ComposableContract(tracked = false) {
onActive { initializationCount++ }
onCommit { commitCount++ }
}
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt
index 5c06179..c346cf9 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposeModelTests.kt
@@ -31,7 +31,6 @@
import androidx.compose.frames.open
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertFalse
import org.junit.After
@@ -128,8 +127,6 @@
@RunWith(AndroidJUnit4::class)
class ModelViewTests : BaseComposeTest() {
- val composer: UiComposer get() = error("should not be called")
-
@After
fun teardown() {
clearRoots()
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposerCompat.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposerCompat.kt
deleted file mode 100644
index dffa262..0000000
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/ComposerCompat.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.test
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
- "This property should not be called directly. It is only used by the compiler.",
- replaceWith = ReplaceWith("currentComposer")
-)
-val composer: EmittableComposer
- get() = error(
- "This property should not be called directly. It is only used by the compiler."
- )
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt
index 16af8c0..aad6292 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/DisposeTests.kt
@@ -17,7 +17,9 @@
package androidx.compose.test
import androidx.compose.Composable
+import androidx.compose.ComposableContract
import androidx.compose.Composition
+import androidx.compose.ExperimentalComposeApi
import androidx.compose.clearRoots
import androidx.compose.onActive
import androidx.compose.onPreCommit
@@ -44,7 +46,8 @@
fun testDisposeComposition() {
val log = mutableListOf<String>()
- val composable = @Composable {
+ @OptIn(ExperimentalComposeApi::class)
+ val composable = @Composable @ComposableContract(tracked = false) {
onPreCommit {
log.add("onPreCommit")
onDispose {
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt
index e15243b..841cc15 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EffectsTests.kt
@@ -34,7 +34,6 @@
import androidx.compose.state
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertTrue
import org.junit.After
@@ -46,8 +45,6 @@
@RunWith(AndroidJUnit4::class)
class EffectsTests : BaseComposeTest() {
- val composer: UiComposer get() = error("should not be called")
-
@After
fun teardown() {
clearRoots()
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt
index f814f7e..0be9e33 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/EmittableComposer.kt
@@ -13,199 +13,55 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@file:OptIn(ComposeCompilerApi::class, ExperimentalComposeApi::class)
package androidx.compose.test
-import android.app.Activity
-import android.content.Context
import android.view.View
-import android.view.ViewGroup
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
+import android.widget.TextView
+import android.widget.Button
+import android.widget.LinearLayout
import androidx.compose.Composable
-import androidx.compose.ComposeCompilerApi
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
-import androidx.compose.Composition
-import androidx.compose.ExperimentalComposeApi
-import androidx.compose.FrameManager
-import androidx.compose.Recomposer
-import androidx.compose.SlotTable
-import androidx.compose.compositionFor
-import androidx.ui.node.UiComposer
+import androidx.ui.viewinterop.emitView
-interface Emittable {
- fun emitInsertAt(index: Int, instance: Emittable)
- fun emitRemoveAt(index: Int, count: Int)
- fun emitMove(from: Int, to: Int, count: Int)
-}
-
-internal class EmittableApplyAdapter : ApplyAdapter<Any> {
- override fun Any.start(instance: Any) {}
- override fun Any.insertAt(index: Int, instance: Any) {
- when (this) {
- is ViewGroup -> insertAt(index, instance)
- is Emittable -> emitInsertAt(index, instance as Emittable)
- else -> error("unexpected node")
- }
- }
-
- override fun Any.removeAt(index: Int, count: Int) {
- when (this) {
- is ViewGroup -> removeViews(index, count)
- is Emittable -> emitRemoveAt(index, count)
- else -> error("unexpected node")
- }
- }
-
- override fun Any.move(from: Int, to: Int, count: Int) {
- when (this) {
- is ViewGroup -> {
- if (from > to) {
- var currentFrom = from
- var currentTo = to
- repeat(count) {
- val view = getChildAt(currentFrom)
- removeViewAt(currentFrom)
- addView(view, currentTo)
- currentFrom++
- currentTo++
- }
- } else {
- repeat(count) {
- val view = getChildAt(from)
- removeViewAt(from)
- addView(view, to - 1)
- }
- }
- }
- is Emittable -> {
- emitMove(from, to, count)
- }
- else -> error("unexpected node")
- }
- }
-
- override fun Any.end(instance: Any, parent: Any) {}
-}
-
-class EmittableComposer(
- val context: Context,
- val root: Any,
- slotTable: SlotTable,
- recomposer: Recomposer
-) : Composer<Any>(
- slotTable,
- Applier(
- root,
- EmittableApplyAdapter()
- ),
- recomposer
+@Composable
+fun TextView(
+ id: Int = 0,
+ text: String = "",
+ onClickListener: View.OnClickListener? = null
) {
- init {
- FrameManager.ensureStarted()
- }
-
- @Suppress("UNCHECKED_CAST")
- fun <T : View> emit(
- key: Any,
- /*crossinline*/
- ctor: (context: Context) -> T,
- update: ViewUpdater<T>.() -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor(context).also { emitNode(it) }
- else useNode() as T
- ViewUpdater(this, node).update()
- endNode()
- }
-
- @Suppress("UNCHECKED_CAST")
- fun <T : ViewGroup> emit(
- key: Any,
- /*crossinline*/
- ctor: (context: Context) -> T,
- update: ViewUpdater<T>.() -> Unit,
- children: () -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor(context).also { emitNode(it) }
- else useNode() as T
- ViewUpdater(this, node).update()
- children()
- endNode()
- }
-
- @Suppress("UNCHECKED_CAST")
- fun <T : Emittable> emit(
- key: Any,
- /*crossinline*/
- ctor: () -> T,
- update: ViewUpdater<T>.() -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor().also { emitNode(it) }
- else useNode() as T
- ViewUpdater(this, node).update()
- endNode()
- }
-
- @Suppress("UNCHECKED_CAST")
- fun <T : Emittable> emit(
- key: Any,
- /*crossinline*/
- ctor: () -> T,
- update: ViewUpdater<T>.() -> Unit,
- children: () -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor().also { emitNode(it) }
- else useNode() as T
- ViewUpdater(this, node).update()
- children()
- endNode()
+ emitView(::TextView) {
+ if (id != 0) it.id = id
+ it.text = text
+ if (onClickListener != null) it.setOnClickListener(onClickListener)
}
}
-typealias ViewUpdater<T> = ComposerUpdater<Any, T>
-
-class ComponentNodeScope { val composer: UiComposer get() = error("should not get called") }
-class EmittableScope { val composer: EmittableComposer get() = error("should not get called") }
-
-class Node(val name: String, var value: String = "") : Emittable {
- val children = mutableListOf<Node>()
-
- override fun emitInsertAt(index: Int, instance: Emittable) {
- children.add(index, instance as Node)
- }
-
- override fun emitRemoveAt(index: Int, count: Int) {
- repeat(count) { children.removeAt(index) }
- }
-
- override fun emitMove(from: Int, to: Int, count: Int) {
- if (from > to) {
- repeat(count) {
- children.add(to + it, children.removeAt(from))
- }
- } else if (from < to) {
- repeat(count) {
- children.add(to - 1, children.removeAt(from))
- }
- }
+@Composable
+fun Button(
+ id: Int = 0,
+ text: String = "",
+ onClickListener: View.OnClickListener? = null
+) {
+ emitView(::Button) {
+ if (id != 0) it.id = id
+ it.text = text
+ if (onClickListener != null) it.setOnClickListener(onClickListener)
}
}
-fun Activity.setEmittableContent(content: @Composable () -> Unit): Composition {
- val root = Node("Root")
- val composition = compositionFor(root, Recomposer.current()) { slotTable, recomposer ->
- EmittableComposer(
- this,
- root,
- slotTable,
- recomposer
- )
- }
- composition.setContent(content)
- return composition
+@Composable
+fun LinearLayout(
+ id: Int = 0,
+ orientation: Int = LinearLayout.VERTICAL,
+ onClickListener: View.OnClickListener? = null,
+ children: @Composable () -> Unit
+) {
+ emitView(
+ ::LinearLayout,
+ {
+ if (id != 0) it.id = id
+ if (onClickListener != null) it.setOnClickListener(onClickListener)
+ it.orientation = orientation
+ },
+ children
+ )
}
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt
index e03fbc7..3fed09d 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/NewCodeGenTests.kt
@@ -17,7 +17,6 @@
package androidx.compose.test
-import android.content.Context
import android.widget.LinearLayout
import android.widget.TextView
import androidx.compose.Composable
@@ -28,7 +27,6 @@
import androidx.compose.setValue
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
import junit.framework.TestCase
import org.junit.After
import org.junit.Rule
@@ -39,8 +37,6 @@
@RunWith(AndroidJUnit4::class)
class NewCodeGenTests : BaseComposeTest() {
- val composer: UiComposer get() = error("should not be called")
-
@After
fun teardown() {
clearRoots()
@@ -276,56 +272,4 @@
}
}
}
-
- @Test
- fun testViewClassWithCtorParametersInvocation() {
- val tvId = 749
-
- class MyTextView(context: Context) : TextView(context) {
- constructor(context: Context, someText: String) : this(context) {
- text = someText
- }
- }
-
- var hello by mutableStateOf("Hello world!")
- compose {
- // <MyTextView someText = hello />
- key(hello) {
- MyTextView(id = tvId, someText = hello)
- }
- }.then { activity ->
- val tv = activity.findViewById(tvId) as TextView
- TestCase.assertEquals("Hello world!", tv.text)
-
- hello = "Salutations!"
- }.then { activity ->
- val tv = activity.findViewById(tvId) as TextView
- TestCase.assertEquals("Salutations!", tv.text)
- }
- }
-
- @Test
- fun testViewClassWithMutableCtorParameter() {
- val tvId = 749
-
- class MyTextView(context: Context, var someValue: String) : TextView(context)
-
- var hello by mutableStateOf("Hello world!")
- var value by mutableStateOf("Unmodified")
- compose {
- // <MyTextView someText = hello />
- MyTextView(id = tvId, someValue = value, text = hello)
- }.then { activity ->
- val tv = activity.findViewById(tvId) as MyTextView
- TestCase.assertEquals("Hello world!", tv.text)
- TestCase.assertEquals("Unmodified", tv.someValue)
-
- hello = "Salutations!"
- value = "Modified"
- }.then { activity ->
- val tv = activity.findViewById(tvId) as MyTextView
- TestCase.assertEquals("Salutations!", tv.text)
- TestCase.assertEquals("Modified", tv.someValue)
- }
- }
}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt
index 5e3d7c8..b7a3fe0 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RecomposerTests.kt
@@ -31,7 +31,6 @@
import androidx.compose.setValue
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertNotSame
@@ -44,8 +43,6 @@
@MediumTest
@RunWith(AndroidJUnit4::class)
class RecomposerTests : BaseComposeTest() {
- val composer: UiComposer get() = error("should not be called")
-
@After
fun teardown() {
clearRoots()
diff --git a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt
index cdf26f7..3e0a8eb 100644
--- a/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt
+++ b/compose/compose-runtime/src/androidAndroidTest/kotlin/androidx/compose/test/RestartTests.kt
@@ -24,7 +24,6 @@
import androidx.compose.mutableStateOf
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
-import androidx.ui.node.UiComposer
import junit.framework.TestCase
import org.junit.After
import org.junit.Rule
@@ -38,8 +37,6 @@
@RunWith(AndroidJUnit4::class)
class RestartTests : BaseComposeTest() {
- val composer: UiComposer get() = error("should not be called")
-
@After
fun teardown() {
clearRoots()
diff --git a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt b/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt
index b261f5b..0de8c00 100644
--- a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt
+++ b/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/ActualAndroid.kt
@@ -16,6 +16,8 @@
package androidx.compose
+import androidx.compose.dispatch.AndroidUiDispatcher
+import androidx.compose.dispatch.MonotonicFrameClock
import androidx.core.os.HandlerCompat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
@@ -65,27 +67,25 @@
// TODO: Our host-side tests still grab the Android actuals based on SDK stubs that return null.
// Satisfy their dependencies.
private val MainAndroidUiDispatcher by lazy {
- if (Looper.getMainLooper() != null) AndroidUiDispatcher.Main
+ if (Looper.getMainLooper() != null) androidx.compose.dispatch.AndroidUiDispatcher.Main
else Dispatchers.Main
}
-private object MainDispatcherCompositionFrameClock : CompositionFrameClock {
+private object MainDispatcherFrameClock : MonotonicFrameClock {
override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R =
withContext(Dispatchers.Main) {
onFrame(System.nanoTime())
}
}
-private val MainAndroidCompositionFrameClock by lazy {
- if (Looper.getMainLooper() != null) AndroidUiDispatcher.Main.compositionFrameClock
- else MainDispatcherCompositionFrameClock
+private val MainAndroidFrameClock by lazy {
+ if (Looper.getMainLooper() != null) AndroidUiDispatcher.Main.frameClock
+ else MainDispatcherFrameClock
}
-internal actual fun mainThreadCompositionDispatcher(): CoroutineDispatcher =
- MainAndroidUiDispatcher
+internal actual fun mainThreadCompositionDispatcher(): CoroutineDispatcher = MainAndroidUiDispatcher
-internal actual fun mainThreadCompositionFrameClock(): CompositionFrameClock =
- MainAndroidCompositionFrameClock
+internal actual fun mainThreadFrameClock(): MonotonicFrameClock = MainAndroidFrameClock
internal actual object Trace {
actual fun beginSection(name: String) = android.os.Trace.beginSection(name)
diff --git a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiDispatcher.kt b/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiDispatcher.kt
deleted file mode 100644
index 85a8311..0000000
--- a/compose/compose-runtime/src/androidMain/kotlin/androidx/compose/AndroidUiDispatcher.kt
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose
-
-import android.view.Choreographer
-import androidx.core.os.HandlerCompat
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Runnable
-import kotlinx.coroutines.runBlocking
-import kotlin.coroutines.CoroutineContext
-
-/**
- * A [CoroutineDispatcher] that will perform dispatch during [choreographer]'s animation frame
- * stage. Suspending will always wait until the next frame.
- */
-@OptIn(ExperimentalStdlibApi::class)
-class AndroidUiDispatcher private constructor(
- val choreographer: Choreographer,
- private val handler: android.os.Handler
-) : CoroutineDispatcher() {
-
- // Guards all properties in this class
- private val lock = Any()
-
- private val toRunTrampolined = ArrayDeque<Runnable>()
- private var toRunOnFrame = mutableListOf<ChoreographerFrameCallback>()
- private var spareToRunOnFrame = mutableListOf<ChoreographerFrameCallback>()
- private var scheduledTrampolineDispatch = false
- private var scheduledFrameDispatch = false
-
- private val dispatchCallback = object : ChoreographerFrameCallback, java.lang.Runnable {
- override fun run() {
- performTrampolineDispatch()
- synchronized(lock) {
- if (toRunOnFrame.isEmpty()) {
- choreographer.removeFrameCallback(this)
- scheduledFrameDispatch = false
- }
- }
- }
-
- override fun doFrame(frameTimeNanos: Long) {
- handler.removeCallbacks(this)
- performTrampolineDispatch()
- performFrameDispatch(frameTimeNanos)
- }
- }
-
- private fun nextTask(): Runnable? = synchronized(lock) {
- toRunTrampolined.removeFirstOrNull()
- }
-
- private fun performTrampolineDispatch() {
- do {
- var task = nextTask()
- while (task != null) {
- task.run()
- task = nextTask()
- }
- } while (
- // We don't dispatch holding the lock so that other tasks can get in on our
- // trampolining time slice, but once we're done, make sure nothing added a new task
- // before we set scheduledDispatch = false, which would prevent the next dispatch
- // from being correctly scheduled. Loop to run these stragglers now.
- synchronized(lock) {
- if (toRunTrampolined.isEmpty()) {
- scheduledTrampolineDispatch = false
- false
- } else true
- }
- )
- }
-
- private fun performFrameDispatch(frameTimeNanos: Long) {
- val toRun = synchronized(lock) {
- if (!scheduledFrameDispatch) return
- scheduledFrameDispatch = false
- val result = toRunOnFrame
- toRunOnFrame = spareToRunOnFrame
- spareToRunOnFrame = result
- result
- }
- for (i in 0 until toRun.size) {
- // This callback can't throw, see AndroidUiCompositionFrameClock
- toRun[i].doFrame(frameTimeNanos)
- }
- toRun.clear()
- }
-
- internal fun postFrameCallback(callback: ChoreographerFrameCallback) {
- synchronized(lock) {
- toRunOnFrame.add(callback)
- if (!scheduledFrameDispatch) {
- scheduledFrameDispatch = true
- choreographer.postFrameCallback(dispatchCallback)
- }
- }
- }
-
- internal fun removeFrameCallback(callback: ChoreographerFrameCallback) {
- synchronized(lock) {
- toRunOnFrame.remove(callback)
- }
- }
-
- val compositionFrameClock: CompositionFrameClock = AndroidUiCompositionFrameClock(choreographer)
-
- override fun dispatch(context: CoroutineContext, block: Runnable) {
- synchronized(lock) {
- toRunTrampolined.addLast(block)
- if (!scheduledTrampolineDispatch) {
- scheduledTrampolineDispatch = true
- handler.post(dispatchCallback)
- if (!scheduledFrameDispatch) {
- scheduledFrameDispatch = true
- choreographer.postFrameCallback(dispatchCallback)
- }
- }
- }
- }
-
- companion object {
- val Main by lazy {
- AndroidUiDispatcher(
- if (isMainThread()) Choreographer.getInstance()
- else runBlocking(Dispatchers.Main) { Choreographer.getInstance() },
- HandlerCompat.createAsync(Looper.getMainLooper())
- )
- }
-
- private val currentThread = ThreadLocal {
- AndroidUiDispatcher(
- Choreographer.getInstance(),
- HandlerCompat.createAsync(Looper.myLooper() ?: error("no Looper on this thread"))
- )
- }
- val CurrentThread: AndroidUiDispatcher get() = currentThread.get()
- }
-}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
index c71b9c7..2dc5cf2 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Ambient.kt
@@ -54,7 +54,7 @@
*
* @sample androidx.compose.samples.consumeAmbient
*/
-@Immutable
+@Stable
sealed class Ambient<T> constructor(defaultFactory: (() -> T)? = null) {
@Suppress("UNCHECKED_CAST")
internal val defaultValueHolder = LazyValueHolder(defaultFactory)
@@ -80,7 +80,7 @@
* @see Ambient
* @see Providers
*/
-@Immutable
+@Stable
abstract class ProvidableAmbient<T> internal constructor(defaultFactory: (() -> T)?) :
Ambient<T> (defaultFactory) {
@@ -119,7 +119,6 @@
*
* @see staticAmbientOf
*/
-@Immutable
internal class StaticProvidableAmbient<T>(defaultFactory: (() -> T)?) :
ProvidableAmbient<T>(defaultFactory) {
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt
index 8bd88c9..6408ee5 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Applier.kt
@@ -17,62 +17,116 @@
package androidx.compose
/**
- * An adapter that performs tree based operations on some tree startNode N without requiring a specific base type for N
+ * An Applier is responsible for applying the tree-based operations that get emitted during a
+ * composition. Every [Composer] has an [Applier] which it uses to [emit].
+ *
+ * A custom [Applier] implementation will be needed in order to utilize Compose to build and
+ * maintain a tree of a novel type.
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @see AbstractApplier
+ * @see compositionFor
+ * @see Composer
+ * @see emit
*/
@ExperimentalComposeApi
-interface ApplyAdapter<N> {
- fun N.start(instance: N)
- fun N.insertAt(index: Int, instance: N)
- fun N.removeAt(index: Int, count: Int)
- fun N.move(from: Int, to: Int, count: Int)
- fun N.end(instance: N, parent: N)
+interface Applier<N> {
+ /**
+ * The node that operations will be applied on at any given time. It is expected that the
+ * value of this property will change as [down] and [up] are called.
+ */
+ val current: N
+
+ /**
+ * Indicates that the applier is getting traversed "down" the tree. When this gets called,
+ * [node] is expected to be a child of [current], and after this operation, [node] is
+ * expected to be the new [current].
+ */
+ fun down(node: N)
+
+ /**
+ * Indicates that the applier is getting traversed "up" the tree. After this operation
+ * completes, the [current] should return the "parent" of the [current] node at the beginning
+ * of this operation.
+ */
+ fun up()
+
+ /**
+ * Indicates that [instance] should be inserted as a child to [current] at [index]
+ */
+ fun insert(index: Int, instance: N)
+
+ /**
+ * Indicates that the children of [current] from [index] to [index] + [count] should be removed.
+ */
+ fun remove(index: Int, count: Int)
+
+ /**
+ * Indicates that the children of [current] from [from] to [from] + [count] should be moved
+ * to [to] + [count].
+ *
+ * The [to] index is related to the position before the change, so, for example, to move an
+ * element at position 1 to after the element at position 2, [from] should be `1` and [to]
+ * should be `3`. If the elements were A B C D E, calling `move(1, 3, 1)` would result in the
+ * elements being reordered to A C B D E.
+ */
+ fun move(from: Int, to: Int, count: Int)
+
+ /**
+ * Reset the applier's state
+ */
+ fun reset()
}
/**
- * A helper class to apply changes to a tree with startNode types N given an apply adapter for type N
+ * An abstract [Applier] implementation that builds the tree "top down".
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @see Applier
+ * @see compositionFor
+ * @see Composer
+ * @see emit
*/
@ExperimentalComposeApi
-class Applier<N>(root: N, private val adapter: ApplyAdapter<N>) {
- private val stack = Stack<N>()
- private var _current: N = root
+abstract class AbstractApplier<T>(val root: T) : Applier<T> {
+ private val stack = mutableListOf<T>()
+ override var current: T = root
- val current: N get() = _current
-
- fun down(node: N) {
- stack.push(current)
- _current = node
- with(adapter) {
- current.start(node)
- }
+ override fun down(node: T) {
+ stack.add(current)
+ current = node
}
- fun up() {
- val node = _current
- _current = stack.pop()
- with(adapter) {
- current.end(node, current)
- }
+ override fun up() {
+ current = stack.removeAt(stack.size - 1)
}
- fun insert(index: Int, instance: N) {
- with(adapter) {
- current.insertAt(index, instance)
- }
- }
-
- fun remove(index: Int, count: Int) {
- with(adapter) {
- current.removeAt(index, count)
- }
- }
-
- fun move(from: Int, to: Int, count: Int) {
- with(adapter) {
- current.move(from, to, count)
- }
- }
-
- fun reset() {
+ override fun reset() {
stack.clear()
+ current = root
+ }
+
+ protected fun MutableList<T>.remove(index: Int, count: Int) {
+ if (count == 1) {
+ removeAt(index)
+ } else {
+ subList(index, index + count).clear()
+ }
+ }
+
+ protected fun MutableList<T>.move(from: Int, to: Int, count: Int) {
+ if (count == 1) {
+ val fromEl = get(from)
+ val toEl = set(to, fromEl)
+ set(from, toEl)
+ } else {
+ val subView = subList(from, from + count)
+ val subCopy = subView.toMutableList()
+ val dest = if (from > to) to else (to - count)
+ subView.clear()
+ addAll(dest, subCopy)
+ }
}
}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt
index 8622a5f..7327e90 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/BroadcastFrameClock.kt
@@ -16,6 +16,7 @@
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.Continuation
@@ -30,7 +31,7 @@
*/
internal class BroadcastFrameClock(
private val onNewAwaiters: (() -> Unit)? = null
-) : CompositionFrameClock {
+) : MonotonicFrameClock {
private data class FrameAwaiter<R>(val onFrame: (Long) -> R, val continuation: Continuation<R>)
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt
index 34e3f4e..5bc48cb 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composable.kt
@@ -34,9 +34,6 @@
@MustBeDocumented
@Retention(AnnotationRetention.BINARY)
@Target(
- // not currently used
- AnnotationTarget.CLASS,
-
// function declarations
// @Composable fun Foo() { ... }
// lambda expressions
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
index 91aec87..b8e52b4 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/ComposableContract.kt
@@ -24,14 +24,18 @@
* Caution: Use of this annotation means that the annotated declaration *MUST* comply with those
* contracts, or else the resulting code's behavior will be undefined.
*
- * @param restartable When false,this will prevent code from being generated which
+ * @param restartable if false, this will prevent code from being generated which
* allow this function's execution to be skipped or restarted. This may be desirable for small
* functions which just directly call another composable function and have very little machinery
* in them directly.
*
- * @param readonly if false, no group will be generated around the body of the function it annotates
+ * @param readonly if true, no group will be generated around the body of the function it annotates
* . This is not safe unless the body of the function only executes "read" operations on the
* passed in composer..
+ *
+ * @param tracked if false, this will disable lambda optimizations such as tracking execution of
+ * composable function expressions or remembering a function expression value based on its
+ * capture variables. This flag is only meaningful when applied to @Composable lambda expressions
*/
@MustBeDocumented
@Retention(AnnotationRetention.BINARY)
@@ -41,5 +45,6 @@
)
annotation class ComposableContract(
val restartable: Boolean = true,
- val readonly: Boolean = false
+ val readonly: Boolean = false,
+ val tracked: Boolean = true
)
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
index 03677e6..23d3903 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composer.kt
@@ -38,7 +38,7 @@
"This property should not be called directly. It is only used by the compiler.",
replaceWith = ReplaceWith("currentComposer")
)
-internal val composer: Composer<*> get() = error(
+val composer: Composer<*> get() = error(
"This property should not be called directly. It is only used by the compiler."
)
@@ -330,11 +330,11 @@
fun <T> changed(value: T): Boolean
}
-// TODO(lmr): this could be named MutableTreeComposer
+// TODO(b/159074030): Consider removing type parameter
/**
* Implementation of a composer for mutable tree.
*/
-open class Composer<N>(
+class Composer<N>(
/**
* Backing storage for the composition
*/
@@ -343,7 +343,8 @@
/**
* An adapter that applies changes to the tree using the Applier abstraction.
*/
- private val applier: Applier<N>,
+ @ComposeCompilerApi
+ val applier: Applier<N>,
/**
* Manager for scheduling recompositions.
@@ -351,6 +352,9 @@
@ExperimentalComposeApi
val recomposer: Recomposer
) {
+ init {
+ FrameManager.ensureStarted()
+ }
private val changes = mutableListOf<Change<N>>()
private val lifecycleObservers = HashMap<
CompositionLifecycleObserverHolder,
@@ -404,7 +408,8 @@
private var insertAnchor: Anchor = insertTable.anchor(0)
private val insertFixups = mutableListOf<Change<N>>()
- protected fun composeRoot(block: () -> Unit) {
+ @InternalComposeApi
+ fun composeRoot(block: () -> Unit) {
startRoot()
startGroup(invocationKey, invocation)
block()
@@ -731,35 +736,13 @@
* does not have the provided key a node with that key is scanned for and moved into the
* current position if found, if no such node is found the composition switches into insert
* mode and a the node is scheduled to be inserted at the current location.
- *
- * @param key the key for the node.
*/
@ComposeCompilerApi
- fun startNode(key: Any) {
- start(nodeKey, key, true, null)
+ fun startNode() {
+ start(nodeKey, null, true, null)
nodeExpected = true
}
- // Deprecated
- @ComposeCompilerApi
- fun <T : N> emitNode(factory: () -> T) {
- validateNodeExpected()
- if (inserting) {
- val insertIndex = nodeIndexStack.peek()
- // The pending is the pending information for where the node is being inserted.
- // pending will be null here when the parent was inserted too.
- groupNodeCount++
- recordFixup { applier, slots, _ ->
- val node = factory()
- slots.node = node
- applier.insert(insertIndex, node)
- applier.down(node)
- }
- } else {
- recordDown(reader.node)
- }
- }
-
/**
* Schedule a node to be created and inserted at the current location. This is only valid to
* call when the composer is inserting.
@@ -787,13 +770,14 @@
* inserting.
*/
@ComposeCompilerApi
- fun emitNode(node: N) {
+ fun emitNode(node: Any) {
validateNodeExpected()
require(inserting) { "emitNode() called when not inserting" }
val insertIndex = nodeIndexStack.peek()
// see emitNode
groupNodeCount++
- writer.node = node
+ @Suppress("UNCHECKED_CAST")
+ writer.node = node as N
recordApplierOperation { applier, _, _ ->
applier.insert(insertIndex, node)
applier.down(node)
@@ -1198,7 +1182,7 @@
if (collectKeySources)
recordSourceKeyInfo(key)
when {
- isNode -> writer.startNode(dataKey)
+ isNode -> writer.startNode(null)
data != null -> writer.startData(key, dataKey, data)
else -> writer.startGroup(key, dataKey)
}
@@ -1267,7 +1251,7 @@
ensureWriter()
writer.beginInsert()
val insertLocation = writer.current
- if (isNode) writer.startNode(dataKey) else writer.startGroup(key, dataKey)
+ if (isNode) writer.startNode(null) else writer.startGroup(key, dataKey)
insertAnchor = writer.anchor(insertLocation)
val insertKeyInfo = KeyInfo(key, -1, 0, -1, 0, writer.parentGroup)
pending.registerInsert(insertKeyInfo, nodeIndex - pending.startIndex)
@@ -2232,7 +2216,7 @@
}
@Suppress("UNCHECKED_CAST")
-/*inline */ class ComposerUpdater<N, T : N>(val composer: Composer<N>, val node: T) {
+/*inline */ class Updater<T>(val composer: Composer<*>, val node: T) {
inline fun set(
value: Int,
/*crossinline*/
@@ -2284,6 +2268,12 @@
// if (!inserting) composer.apply(value, appliedBlock)
}
}
+
+ inline fun reconcile(
+ block: T.() -> Unit
+ ) {
+ node.block()
+ }
}
/**
@@ -2425,10 +2415,18 @@
private fun Boolean.asInt() = if (this) 1 else 0
private fun Int.asBool() = this != 0
+@Deprecated(
+ "This no longer has any effect"
+)
object NullCompilationScope {
val composer = Unit
}
+@Suppress("DEPRECATION")
+@Deprecated(
+ "This no longer has any effect",
+ ReplaceWith("block()")
+)
inline fun <T> escapeCompose(block: NullCompilationScope.() -> T) = NullCompilationScope.block()
@Composable
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt
index bccf965..3469410 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Composition.kt
@@ -52,6 +52,7 @@
* @param parent The parent composition reference, if applicable. Default is null.
* @param composerFactory The factory used to created a [Composer] to be used by the composition.
*/
+@Deprecated("Use the compositionFor(...) overload that accepts an Applier<N>")
fun compositionFor(
container: Any,
recomposer: Recomposer,
@@ -76,6 +77,7 @@
* @param parent The parent composition reference, if applicable. Default is null.
* @param composerFactory The factory used to created a [Composer] to be used by the composition.
*/
+@Suppress("DEPRECATION")
@Deprecated(
"Specify the Recomposer explicitly",
ReplaceWith(
@@ -90,6 +92,46 @@
): Composition = compositionFor(container, Recomposer.current(), parent, composerFactory)
/**
+ * This method is the way to initiate a composition. Optionally, a [parent]
+ * [CompositionReference] can be provided to make the composition behave as a sub-composition of
+ * the parent.
+ *
+ * It is important to call [Composition.dispose] whenever this [key] is no longer needed in
+ * order to release resources.
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @param key The object this composition will be tied to. Only one [Composition] will be created
+ * for a given [key]. If the same [key] is passed in subsequent calls, the same [Composition]
+ * instance will be returned.
+ * @param applier The [Applier] instance to be used in the composition.
+ * @param recomposer The [Recomposer] instance to be used for composition.
+ * @param parent The parent composition reference, if applicable. Default is null.
+ * @param onCreated A function which will be executed only when the Composition is created.
+ *
+ * @see Applier
+ * @see Composition
+ * @see Recomposer
+ */
+@ExperimentalComposeApi
+fun compositionFor(
+ key: Any,
+ applier: Applier<*>,
+ recomposer: Recomposer,
+ parent: CompositionReference? = null,
+ onCreated: () -> Unit = {}
+): Composition = Compositions.findOrCreate(key) {
+ CompositionImpl(
+ recomposer,
+ parent,
+ composerFactory = { slots, rcmpsr -> Composer(slots, applier, rcmpsr) },
+ onDispose = { Compositions.onDisposed(key) }
+ ).also {
+ onCreated()
+ }
+}
+
+/**
* @param parent An optional reference to the parent composition.
* @param composerFactory A function to create a composer object, for use during composition
* @param onDispose A callback to be triggered when [dispose] is called.
@@ -98,7 +140,7 @@
private val recomposer: Recomposer,
parent: CompositionReference?,
composerFactory: (SlotTable, Recomposer) -> Composer<*>,
- private val onDispose: (() -> Unit)
+ private val onDispose: () -> Unit
) : Composition {
private val slotTable: SlotTable = SlotTable()
private val composer: Composer<*> = composerFactory(slotTable, recomposer).also {
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt
index 6a2e1c8..58651a3 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/CompositionFrameClock.kt
@@ -17,27 +17,16 @@
// TODO(b/158105080): make part of ComposeRuntime
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
+import androidx.compose.dispatch.withFrameMillis as withFrameMillisDispatch
+
/**
* Provides a time source for display frames for use in composition.
* This may be used for matching timing with the refresh rate of a display
* or otherwise synchronizing with a desired frame rate of composition updates.
*/
-interface CompositionFrameClock {
- /**
- * Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
- * in nanoseconds in the calling context of frame dispatch, then resumes with the result from
- * [onFrame].
- *
- * `frameTimeNanos` should be used when calculating animation time deltas from frame to frame
- * as it may be normalized to the target time for the frame, not necessarily a direct,
- * "now" value.
- *
- * The time base of the value provided by [withFrameNanos] is implementation defined.
- * Time values provided are monotonically increasing; after a call to [withFrameNanos]
- * completes it must not provide the same value again for a subsequent call.
- */
- suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R
-
+@Deprecated("Moved and renamed to MonotonicFrameClock")
+interface CompositionFrameClock : MonotonicFrameClock {
/**
* Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
* in nanoseconds in the calling context of frame dispatch, then resumes with the result from
@@ -70,10 +59,17 @@
* [CompositionFrameClock.withFrameMillis] completes it must not provide the same value again for
* a subsequent call.
*/
-@Suppress("UnnecessaryLambdaCreation")
+@Deprecated(
+ "CompositionFrameClock moved and renamed to MonotonicFrameClock",
+ ReplaceWith(
+ "withFrameMillis(onFrame)",
+ "androidx.compose.dispatch.withFrameMillis"
+ )
+)
+@Suppress("UnnecessaryLambdaCreation", "DEPRECATION")
suspend inline fun <R> CompositionFrameClock.withFrameMillis(
crossinline onFrame: (frameTimeMillis: Long) -> R
-): R = withFrameNanos { onFrame(it / 1_000_000L) }
+): R = withFrameMillisDispatch(onFrame)
/**
* Suspends until a new frame is requested, immediately invokes [onFrame] with the frame time
@@ -88,6 +84,7 @@
* Time values provided are monotonically increasing; after a call to [awaitFrameNanos]
* completes it must not provide the same value again for a subsequent call.
*/
+@Suppress("DEPRECATION")
@Deprecated(
"renamed to withFrameMillis",
ReplaceWith("withFrameMillis(onFrame)", "androidx.compose.withFrameMillis")
@@ -106,6 +103,7 @@
* Time values returned are monotonically increasing; after a call to [awaitFrameNanos]
* returns it must not return the same value again for a subsequent call.
*/
+@Suppress("DEPRECATION")
@Deprecated(
"callers will resume after missing the frame on most dispatchers",
ReplaceWith("withFrameNanos { it }")
@@ -122,6 +120,7 @@
* Time values returned are monotonically increasing; after a call to [awaitFrameMillis]
* returns it must not return the same value again for a subsequent call.
*/
+@Suppress("DEPRECATION")
@Deprecated(
"callers will resume after missing the frame on most dispatchers",
ReplaceWith("withFrameMillis { it }", "androidx.compose.withFrameMillis")
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Emit.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Emit.kt
new file mode 100644
index 0000000..c26ae9b
--- /dev/null
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Emit.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ComposeCompilerApi::class, ExperimentalComposeApi::class)
+package androidx.compose
+
+/**
+ * Emits a node into the composition of type [T].
+ *
+ * This function will throw a runtime exception if [E] is not a subtype of the applier of the
+ * [currentComposer].
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @param ctor A function which will create a new instance of [T]. This function is NOT
+ * guaranteed to be called in place.
+ * @param update A function to perform updates on the node. This will run every time emit is
+ * executed. This function is called in place and will be inlined.
+ *
+ * @see Updater
+ * @see Applier
+ * @see emit
+ * @see compositionFor
+ */
+@OptIn(ComposeCompilerApi::class)
+@Composable inline fun <T : Any, reified E : Applier<*>> emit(
+ noinline ctor: () -> T,
+ update: Updater<T>.() -> Unit
+) {
+ require(currentComposer.applier is E)
+ currentComposer.startNode()
+ val node = if (currentComposer.inserting)
+ ctor().also { currentComposer.emitNode(it) }
+ else
+ @Suppress("UNCHECKED_CAST")
+ currentComposer.useNode() as T
+ Updater(currentComposer, node).update()
+ currentComposer.endNode()
+}
+
+// TODO(lmr): make assert more informative
+// TODO(lmr): consider invoking children manually
+// TODO(lmr): consider ComposableContract for this
+/**
+ * Emits a node into the composition of type [T]. Nodes emitted inside of [children] will become
+ * children of the emitted node.
+ *
+ * This function will throw a runtime exception if [E] is not a subtype of the applier of the
+ * [currentComposer].
+ *
+ * @sample androidx.compose.samples.CustomTreeComposition
+ *
+ * @param ctor A function which will create a new instance of [T]. This function is NOT
+ * guaranteed to be called in place.
+ * @param update A function to perform updates on the node. This will run every time emit is
+ * executed. This function is called in place and will be inlined.
+ * @param children the composable content that will emit the "children" of this node.
+ *
+ * @see Updater
+ * @see Applier
+ * @see emit
+ * @see compositionFor
+ */
+@OptIn(ComposeCompilerApi::class)
+@Composable
+inline fun <T : Any, reified E : Applier<*>> emit(
+ noinline ctor: () -> T,
+ update: Updater<T>.() -> Unit,
+ children: @Composable () -> Unit
+) {
+ require(currentComposer.applier is E)
+ currentComposer.startNode()
+ val node = if (currentComposer.inserting)
+ ctor().also { currentComposer.emitNode(it) }
+ else
+ @Suppress("UNCHECKED_CAST")
+ currentComposer.useNode() as T
+ Updater(currentComposer, node).update()
+ children()
+ currentComposer.endNode()
+}
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt
index 9fca4c6..af83486 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Expect.kt
@@ -16,6 +16,7 @@
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
import kotlinx.coroutines.CoroutineDispatcher
// TODO(aelias): Mark the typealiases internal when https://youtrack.jetbrains.com/issue/KT-36695 is fixed.
@@ -99,7 +100,7 @@
}
internal expect fun mainThreadCompositionDispatcher(): CoroutineDispatcher
-internal expect fun mainThreadCompositionFrameClock(): CompositionFrameClock
+internal expect fun mainThreadFrameClock(): MonotonicFrameClock
@MustBeDocumented
@Retention(AnnotationRetention.BINARY)
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt
index 14991fa..62260a5 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Recomposer.kt
@@ -17,6 +17,7 @@
@file:OptIn(InternalComposeApi::class)
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,7 +35,7 @@
* [frameClock] is used to align changes with display frames.
*/
suspend fun withRunningRecomposer(
- frameClock: CompositionFrameClock,
+ frameClock: MonotonicFrameClock,
block: suspend CoroutineScope.(recomposer: Recomposer) -> Unit
): Unit = coroutineScope {
val recomposer = Recomposer()
@@ -82,7 +83,7 @@
}
}
}
- val frameClock: CompositionFrameClock get() = broadcastFrameClock
+ val frameClock: MonotonicFrameClock get() = broadcastFrameClock
/**
* Await the invalidation of any associated [Composer]s, recompose them, and apply their
@@ -94,7 +95,7 @@
* This method never returns. Cancel the calling [CoroutineScope] to stop.
*/
suspend fun runRecomposeAndApplyChanges(
- frameClock: CompositionFrameClock
+ frameClock: MonotonicFrameClock
): Nothing {
coroutineScope {
recomposeAndApplyChanges(this, frameClock, Long.MAX_VALUE)
@@ -114,7 +115,7 @@
*/
suspend fun recomposeAndApplyChanges(
applyCoroutineScope: CoroutineScope,
- frameClock: CompositionFrameClock,
+ frameClock: MonotonicFrameClock,
frameCount: Long
) {
var framesRemaining = frameCount
@@ -200,8 +201,8 @@
private class CompositionCoroutineScopeImpl(
override val coroutineContext: CoroutineContext,
- frameClock: CompositionFrameClock
- ) : CompositionCoroutineScope(), CompositionFrameClock by frameClock
+ frameClock: MonotonicFrameClock
+ ) : CompositionCoroutineScope(), MonotonicFrameClock by frameClock
/**
* Implementation note: we launch effects undispatched so they can begin immediately during
@@ -330,7 +331,7 @@
mainRecomposer = it
@OptIn(ExperimentalCoroutinesApi::class)
mainScope.launch(start = CoroutineStart.UNDISPATCHED) {
- it.runRecomposeAndApplyChanges(mainThreadCompositionFrameClock())
+ it.runRecomposeAndApplyChanges(mainThreadFrameClock())
}
}
}
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt
index 24fdd18..cc65b2d 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/SuspendingEffects.kt
@@ -18,6 +18,7 @@
@file:OptIn(InternalComposeApi::class)
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
@@ -43,12 +44,12 @@
/**
* A [CoroutineScope] used for launching [side effects][launchInComposition] of a composition
- * that also permits [awaiting][CompositionFrameClock.withFrameNanos] the next presentation
+ * that also permits [awaiting][MonotonicFrameClock.withFrameNanos] the next presentation
* frame of the composition. This can be useful for performing the next action of an animation
* while the effect is still present in the composition.
*/
// TODO Make this an interface once it doesn't experience compiler issues
-abstract class CompositionCoroutineScope : CoroutineScope, CompositionFrameClock {
+abstract class CompositionCoroutineScope : CoroutineScope, MonotonicFrameClock {
// This method deliberately shadows the awaitFrame method from kotlinx-coroutines-android
// to redirect usage to the CompositionFrameClock API in effect blocks.
@Suppress("RedundantSuspendModifier")
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt
index 9fe14cf..f77a3fd 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/Untracked.kt
@@ -27,4 +27,9 @@
AnnotationTarget.FUNCTION
)
@ExperimentalComposeApi
+@Deprecated(
+ "This is now implemented as a composable contract",
+ ReplaceWith("@ComposableContract(tracked=false)", "androidx.compose.ComposableContract"),
+ DeprecationLevel.ERROR
+)
annotation class Untracked
\ No newline at end of file
diff --git a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/RestartableFunction.kt b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/ComposableLambda.kt
similarity index 97%
rename from compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/RestartableFunction.kt
rename to compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/ComposableLambda.kt
index 234c85a..0a72f697 100644
--- a/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/RestartableFunction.kt
+++ b/compose/compose-runtime/src/commonMain/kotlin/androidx/compose/internal/ComposableLambda.kt
@@ -44,7 +44,7 @@
*/
@Stable
@ComposeCompilerApi
-class RestartableFunction<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16,
+class ComposableLambda<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16,
P17, P18, R>(
val key: Int,
private val tracked: Boolean
@@ -1140,20 +1140,20 @@
this == null || !this.valid || this == other || this.anchor == other.anchor
@ComposeCompilerApi
-private typealias RFunction = RestartableFunction<Any, Any, Any, Any, Any, Any, Any, Any, Any, Any,
+private typealias CLambda = ComposableLambda<Any, Any, Any, Any, Any, Any, Any, Any, Any, Any,
Any, Any, Any, Any, Any, Any, Any, Any, Any>
@Suppress("unused")
@ComposeCompilerApi
-fun restartableFunction(composer: Composer<*>, key: Int, tracked: Boolean, block: Any): RFunction {
+fun composableLambda(composer: Composer<*>, key: Int, tracked: Boolean, block: Any): CLambda {
composer.startReplaceableGroup(key)
val slot = composer.nextSlot()
val result = if (slot === SlotTable.EMPTY) {
- val value = RFunction(key, tracked)
+ val value = CLambda(key, tracked)
composer.updateValue(value)
value
} else {
- slot as RFunction
+ slot as CLambda
}
result.update(block)
composer.endReplaceableGroup()
@@ -1162,5 +1162,5 @@
@Suppress("unused")
@ComposeCompilerApi
-fun restartableFunctionInstance(key: Int, tracked: Boolean, block: Any) =
- RFunction(key, tracked).apply { update(block) }
+fun composableLambdaInstance(key: Int, tracked: Boolean, block: Any) =
+ CLambda(key, tracked).apply { update(block) }
diff --git a/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt b/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt
index d70f5c6..e9a170d 100644
--- a/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt
+++ b/compose/compose-runtime/src/desktopMain/kotlin/androidx/compose/ActualDesktop.kt
@@ -16,6 +16,7 @@
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
import javax.swing.JComponent
import javax.swing.SwingUtilities
import kotlinx.coroutines.CoroutineDispatcher
@@ -131,15 +132,14 @@
keyInfo.clear()
}
-private object MainCompositionFrameClock : CompositionFrameClock {
+private object MainDispatcherFrameClock : MonotonicFrameClock {
override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R =
withContext(Dispatchers.Main) {
onFrame(java.lang.System.nanoTime())
}
}
-internal actual fun mainThreadCompositionFrameClock(): CompositionFrameClock =
- MainCompositionFrameClock
+internal actual fun mainThreadFrameClock(): MonotonicFrameClock = MainDispatcherFrameClock
internal actual fun mainThreadCompositionDispatcher(): CoroutineDispatcher =
Dispatchers.Main
diff --git a/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/RestartableFunctionN.kt b/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/ComposableLambdaN.kt
similarity index 91%
rename from compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/RestartableFunctionN.kt
rename to compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/ComposableLambdaN.kt
index f1396ed..6dba142 100644
--- a/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/RestartableFunctionN.kt
+++ b/compose/compose-runtime/src/jvmMain/kotlin/androidx/compose/internal/ComposableLambdaN.kt
@@ -29,7 +29,7 @@
@Stable
@ComposeCompilerApi
-class RestartableFunctionN<R>(
+class ComposableLambdaN<R>(
val key: Int,
private val tracked: Boolean,
override val arity: Int
@@ -93,22 +93,22 @@
@Suppress("unused")
@ComposeCompilerApi
-fun restartableFunctionN(
+fun composableLambdaN(
composer: Composer<*>,
key: Int,
tracked: Boolean,
arity: Int,
block: Any
-): RestartableFunctionN<*> {
+): ComposableLambdaN<*> {
composer.startReplaceableGroup(key)
val slot = composer.nextSlot()
val result = if (slot === SlotTable.EMPTY) {
- val value = RestartableFunctionN<Any>(key, tracked, arity)
+ val value = ComposableLambdaN<Any>(key, tracked, arity)
composer.updateValue(value)
value
} else {
@Suppress("UNCHECKED_CAST")
- slot as RestartableFunctionN<Any>
+ slot as ComposableLambdaN<Any>
}
result.update(block)
composer.endReplaceableGroup()
@@ -117,9 +117,9 @@
@Suppress("unused")
@ComposeCompilerApi
-fun restartableFunctionNInstance(
+fun composableLambdaNInstance(
key: Int,
tracked: Boolean,
arity: Int,
block: Any
-): RestartableFunctionN<*> = RestartableFunctionN<Any>(key, tracked, arity).apply { update(block) }
+): ComposableLambdaN<*> = ComposableLambdaN<Any>(key, tracked, arity).apply { update(block) }
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt
index 3fd352b..0a69115 100644
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/CompositionTests.kt
@@ -17,14 +17,16 @@
@file:OptIn(ExperimentalComposeApi::class, InternalComposeApi::class)
package androidx.compose
+import androidx.compose.dispatch.MonotonicFrameClock
import androidx.compose.mock.Contact
import androidx.compose.mock.ContactModel
import androidx.compose.mock.MockComposeScope
-import androidx.compose.mock.MockViewComposer
+import androidx.compose.mock.MockViewListValidator
import androidx.compose.mock.MockViewValidator
import androidx.compose.mock.Point
import androidx.compose.mock.Report
import androidx.compose.mock.View
+import androidx.compose.mock.ViewApplier
import androidx.compose.mock.contact
import androidx.compose.mock.edit
import androidx.compose.mock.linear
@@ -36,7 +38,6 @@
import androidx.compose.mock.selectContact
import androidx.compose.mock.skip
import androidx.compose.mock.text
-import androidx.compose.mock.validate
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@@ -61,11 +62,11 @@
@Test
fun testComposeAModel() {
val model = testModel()
- val myComposer = compose {
+ val result = compose {
selectContact(model)
}
- validate(myComposer.root) {
+ result.validate {
linear {
linear {
text("Filter:")
@@ -86,13 +87,13 @@
@Test
fun testRecomposeWithoutChanges() {
val model = testModel()
- val myComposer = compose {
+ val result = compose {
selectContact(model)
}
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) {
+ result.validate {
selectContact(model)
}
}
@@ -102,12 +103,12 @@
val model =
testModel(mutableListOf(bob, jon))
var changed = {}
- val myComposer = compose {
+ val result = compose {
changed = invalidate
selectContact(model)
}
- validate(myComposer.root) {
+ result.validate {
linear {
skip()
linear {
@@ -122,9 +123,9 @@
model.add(steve, after = bob)
changed()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
skip()
linear {
@@ -149,16 +150,16 @@
)
)
var changed = {}
- val myComposer = compose {
+ val result = compose {
changed = invalidate
selectContact(model)
}
model.move(steve, after = jon)
changed()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
skip()
linear {
@@ -183,16 +184,16 @@
)
)
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
selectContact(model)
}
model.filter = "Jon"
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
skip()
linear {
@@ -213,11 +214,11 @@
clark_reports_to_lois
)
- val myComposer = compose {
+ val result = compose {
reportsReport(reports)
}
- validate(myComposer.root) {
+ result.validate {
reportsReport(reports)
}
}
@@ -230,7 +231,7 @@
clark_reports_to_lois
)
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
reportsReport(reports)
}
@@ -241,9 +242,9 @@
rob_reports_to_alice
)
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
reportsReport(reports)
}
}
@@ -275,22 +276,22 @@
}
text("After")
}
- val myComposer = compose {
+ val result = compose {
composition()
}
- validate(myComposer.root) {
+ result.validate {
composition()
}
includeA = false
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) {
+ result.expectChanges()
+ result.validate {
composition()
}
includeA = true
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) {
+ result.expectChanges()
+ result.validate {
composition()
}
}
@@ -316,14 +317,14 @@
repeat(of = chars) { c -> textOf(c) }
}
- val myComposer = compose {
+ val result = compose {
changed = invalidate
chars(chars)
chars(chars)
chars(chars)
}
- validate(myComposer.root) {
+ result.validate {
validatechars(chars)
validatechars(chars)
validatechars(chars)
@@ -331,9 +332,9 @@
chars = listOf('a', 'b', 'x', 'c')
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
validatechars(chars)
validatechars(chars)
validatechars(chars)
@@ -343,13 +344,13 @@
@Test
fun testSimpleMemoize() {
val points = listOf(Point(1, 2), Point(2, 3))
- val myComposer = compose {
+ val result = compose {
points(points)
}
- validate(myComposer.root) { points(points) }
+ result.validate { points(points) }
- val changes = myComposer.recompose()
+ val changes = result.recompose()
assertFalse(changes)
}
@@ -362,12 +363,12 @@
Point(6, 7)
)
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
points(points)
}
- validate(myComposer.root) { points(points) }
+ result.validate { points(points) }
points = listOf(
Point(1, 2),
@@ -376,9 +377,9 @@
Point(6, 7)
)
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { points(points) }
+ result.validate { points(points) }
}
@Test
@@ -406,11 +407,11 @@
rob_reports_to_alice,
clark_reports_to_lois
)
- val myComposer = compose {
+ val result = compose {
reportsReport(reports)
}
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -418,7 +419,7 @@
}
}
- myComposer.expectNoChanges()
+ result.expectNoChanges()
}
@Test
@@ -435,11 +436,11 @@
}
}
- val myComposer = compose {
+ val result = compose {
Two(41, 42)
}
- validate(myComposer.root) {
+ result.validate {
two(41, 42)
}
}
@@ -458,11 +459,11 @@
}
}
- val myComposer = compose {
+ val result = compose {
Three(41, 42, 43)
}
- validate(myComposer.root) {
+ result.validate {
three(41, 42, 43)
}
}
@@ -486,11 +487,11 @@
}
}
- val myComposer = compose {
+ val result = compose {
Four(41, 42, 43, 44)
}
- validate(myComposer.root) {
+ result.validate {
four(41, 42, 43, 44)
}
}
@@ -548,13 +549,13 @@
test(showThree)
}
- val myComposer = compose(block = composition)
- validate(myComposer.root, block = validation)
+ val result = compose(block = composition)
+ result.validate(validation)
showThree = true
recomposeTest()
- myComposer.expectChanges()
- validate(myComposer.root, block = validation)
+ result.expectChanges()
+ result.validate(validation)
}
@Test
@@ -573,20 +574,20 @@
var value = 42
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
callOne(value)
}
- validate(myComposer.root) {
+ result.validate {
one(42)
}
value = 43
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
one(43)
}
}
@@ -607,25 +608,25 @@
var value = 42
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
callOne(value)
}
- validate(myComposer.root) {
+ result.validate {
one(42)
}
value = 43
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
one(43)
}
changed!!()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
}
@Test
@@ -656,11 +657,11 @@
jim_reports_to_sally,
rob_reports_to_alice,
clark_reports_to_lois, r)
- val myComposer = compose {
+ val result = compose {
reportsReport(reports)
}
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -669,7 +670,7 @@
}
}
- myComposer.expectNoChanges()
+ result.expectNoChanges()
// Demote Perry
r.from = "Perry"
@@ -678,9 +679,9 @@
// Compose only the Lois report
recomposeLois?.let { it() }
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -721,11 +722,11 @@
jim_reports_to_sally,
rob_reports_to_alice,
clark_reports_to_lois, r)
- val myComposer = compose {
+ val result = compose {
reportsReport(reports)
}
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -734,7 +735,7 @@
}
}
- myComposer.expectNoChanges()
+ result.expectNoChanges()
// Demote Perry
r.from = "Perry"
@@ -746,9 +747,9 @@
// Compose only the Lois report
recomposeLois?.let { it() }
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -802,12 +803,12 @@
var filter = all
var changed = {}
- val myComposer = compose {
+ val result = compose {
changed = invalidate
reportsReport(reports, filter)
}
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -818,9 +819,9 @@
filter = notLois
changed()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -829,9 +830,9 @@
// Invalidate Lois which is now removed.
recomposeLois()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) {
+ result.validate {
linear {
reportsTo(jim_reports_to_sally)
reportsTo(rob_reports_to_alice)
@@ -862,16 +863,16 @@
text("value = $value")
}
- val myComposer = compose {
+ val result = compose {
test(1)
}
- validate(myComposer.root) { test(1) }
+ result.validate { test(1) }
assertEquals(1, count)
changed!!()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
// Expect the previous instance to be remembered
assertEquals(1, count)
@@ -898,23 +899,23 @@
var value = 1
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
test(value)
}
- validate(myComposer.root) { test(1) }
+ result.validate { test(1) }
value = 2
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { test(2) }
+ result.validate { test(2) }
changed!!()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { test(2) }
+ result.validate { test(2) }
assertEquals(2, count)
}
@@ -942,24 +943,24 @@
var p2 = 2
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
test(p1, p2)
}
- validate(myComposer.root) { test(1, 2) }
+ result.validate { test(1, 2) }
p1 = 2
p2 = 3
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { test(2, 3) }
+ result.validate { test(2, 3) }
changed!!()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { test(2, 3) }
+ result.validate { test(2, 3) }
assertEquals(2, count)
}
@@ -985,23 +986,23 @@
var p3 = 3
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
test(1, 2, p3)
}
- validate(myComposer.root) { test(1, 2, 3) }
+ result.validate { test(1, 2, 3) }
p3 = 4
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { test(1, 2, 4) }
+ result.validate { test(1, 2, 4) }
changed!!()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { test(1, 2, 4) }
+ result.validate { test(1, 2, 4) }
assertEquals(2, count)
}
@@ -1029,24 +1030,24 @@
var p4 = 4
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
test(1, 2, p3, p4)
}
- validate(myComposer.root) { test(1, 2, 3, 4) }
+ result.validate { test(1, 2, 3, 4) }
p3 = 4
p4 = 5
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { test(1, 2, 4, 5) }
+ result.validate { test(1, 2, 4, 5) }
changed!!()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { test(1, 2, 4, 5) }
+ result.validate { test(1, 2, 4, 5) }
assertEquals(2, count)
}
@@ -1072,23 +1073,23 @@
var lastParameter = 5
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
test(1, 2, 3, 4, lastParameter)
}
- validate(myComposer.root) { test(1, 2, 3, 4, 5) }
+ result.validate { test(1, 2, 3, 4, 5) }
lastParameter = 6
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { test(1, 2, 3, 4, 6) }
+ result.validate { test(1, 2, 3, 4, 6) }
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { test(1, 2, 3, 4, 6) }
+ result.validate { test(1, 2, 3, 4, 6) }
assertEquals(2, count)
}
@@ -1116,15 +1117,15 @@
}
}
- val myComposer = compose { composition() }
+ val result = compose { composition() }
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
for (i in 1..10) {
values.add(i)
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) { composition() }
+ result.expectChanges()
+ result.validate { composition() }
}
}
@@ -1164,14 +1165,14 @@
}
}
- val myComposer = compose { composition() }
- validate(myComposer.root) { composition() }
+ val result = compose { composition() }
+ result.validate { composition() }
threeVisible = true
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
}
@Test
@@ -1191,16 +1192,16 @@
}
}
- val myComposer = compose { composition() }
+ val result = compose { composition() }
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
text = "Ending"
myInvalidate?.let { it() }
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
}
@Test
@@ -1230,22 +1231,22 @@
}
}
- val myComposer = compose { composition() }
+ val result = compose { composition() }
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
text = "Ending"
includeNested = false
invalidate1()
invalidate2()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
}
@Test
@@ -1275,22 +1276,22 @@
}
}
- val myComposer = compose { composition() }
+ val result = compose { composition() }
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
text = "Ending"
includeNested = false
invalidate1?.invoke()
invalidate2?.invoke()
- myComposer.expectChanges()
+ result.expectChanges()
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
- myComposer.expectNoChanges()
+ result.expectNoChanges()
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
}
// b/132638679
@@ -1318,16 +1319,16 @@
}
}
- val myComposer = compose { composition() }
+ val result = compose { composition() }
texts = 4
invalidateOuter?.invoke()
invalidateInner?.invoke()
- myComposer.expectChanges()
+ result.expectChanges()
texts = 3
invalidateOuter?.invoke()
- myComposer.expectChanges()
+ result.expectChanges()
}
@Test
@@ -1357,17 +1358,17 @@
}
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
composition()
}
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
assertEquals(1, lifecycleObject.count, "object should have been notified of an enter")
changed!!()
- myComposer.expectNoChanges()
- validate(myComposer.root) { composition() }
+ result.expectNoChanges()
+ result.validate { composition() }
assertEquals(1, lifecycleObject.count, "Object should have only been notified once")
}
@@ -1408,17 +1409,17 @@
}
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
composition()
}
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
assertEquals(1, lifecycleObject.count, "object should have been notified of an enter")
changed!!()
- myComposer.expectNoChanges()
- validate(myComposer.root) { composition() }
+ result.expectNoChanges()
+ result.validate { composition() }
assertEquals(1, lifecycleObject.count, "Object should have only been notified once")
}
@@ -1460,24 +1461,24 @@
var changed: (() -> Unit)? = null
var value = true
- val myComposer = compose {
+ val result = compose {
changed = invalidate
composition(value)
}
- validate(myComposer.root) { composition(true) }
+ result.validate { composition(true) }
assertEquals(1, lifecycleObject.count, "object should have been notified of an enter")
changed!!()
- myComposer.expectNoChanges()
- validate(myComposer.root) { composition(true) }
+ result.expectNoChanges()
+ result.validate { composition(true) }
assertEquals(1, lifecycleObject.count, "Object should have only been notified once")
value = false
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) { composition(false) }
+ result.expectChanges()
+ result.validate { composition(false) }
assertEquals(0, lifecycleObject.count, "Object should have been notified of a leave")
}
@@ -1552,11 +1553,11 @@
var b = false
var c = false
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
composition(a = a, b = b, c = c)
}
- validate(myComposer.root) {
+ result.validate {
composition(
a = true,
b = false,
@@ -1573,8 +1574,8 @@
expectedEnter = false
expectedLeave = false
changed!!()
- myComposer.expectNoChanges()
- validate(myComposer.root) {
+ result.expectNoChanges()
+ result.validate {
composition(
a = true,
b = false,
@@ -1593,8 +1594,8 @@
b = true
c = false
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) {
+ result.expectChanges()
+ result.validate {
composition(
a = false,
b = true,
@@ -1609,8 +1610,8 @@
b = false
c = true
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) {
+ result.expectChanges()
+ result.validate {
composition(
a = false,
b = false,
@@ -1625,8 +1626,8 @@
b = false
c = false
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) {
+ result.expectChanges()
+ result.validate {
composition(
a = true,
b = false,
@@ -1641,8 +1642,8 @@
b = false
c = false
changed!!()
- myComposer.expectChanges()
- validate(myComposer.root) {
+ result.expectChanges()
+ result.validate {
composition(
a = false,
b = false,
@@ -1696,25 +1697,25 @@
}
}
- val myComposer = compose {
+ val result = compose {
changed = invalidate
composition(obj = lifecycleObject)
}
- validate(myComposer.root) { composition() }
+ result.validate { composition() }
assertEquals(1, lifecycleObject1.count, "first object should enter")
assertEquals(0, lifecycleObject2.count, "second object should not have entered")
lifecycleObject = lifecycleObject2
changed()
- myComposer.expectChanges()
- validate(myComposer.root) { composition() }
+ result.expectChanges()
+ result.validate { composition() }
assertEquals(0, lifecycleObject1.count, "first object should have left")
assertEquals(1, lifecycleObject2.count, "second object should have entered")
lifecycleObject = object {}
changed()
- myComposer.expectChanges()
- validate(myComposer.root) { composition() }
+ result.expectChanges()
+ result.validate { composition() }
assertEquals(0, lifecycleObject1.count, "first object should have left")
assertEquals(0, lifecycleObject2.count, "second object should have left")
}
@@ -1799,7 +1800,7 @@
var value = true
var changed: (() -> Unit)? = null
- val myComposer = compose {
+ val result = compose {
changed = invalidate
composition(value)
}
@@ -1811,7 +1812,7 @@
value = false
changed!!()
- myComposer.expectChanges()
+ result.expectChanges()
assertTrue(
objects.mapNotNull { it as? Counted }.map { it.count == 0 }.all { it },
@@ -1847,16 +1848,16 @@
@Composable
fun MockComposeScope.test() {
outerInvalidate = invalidate
- outerKeys.add(composer.currentCompoundKeyHash)
+ outerKeys.add(currentComposer.currentCompoundKeyHash)
Container {
innerInvalidate = invalidate
- innerKeys.add(composer.currentCompoundKeyHash)
+ innerKeys.add(currentComposer.currentCompoundKeyHash)
}
// asserts that the key is correctly rolled back after start and end of Observe
- assertEquals(outerKeys.last(), composer.currentCompoundKeyHash)
+ assertEquals(outerKeys.last(), currentComposer.currentCompoundKeyHash)
}
- val myComposer = compose {
+ val result = compose {
test()
}
@@ -1865,12 +1866,12 @@
previousOuterKeysSize = outerKeys.size
outerInvalidate()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
assertNotEquals(previousOuterKeysSize, outerKeys.size)
previousInnerKeysSize = innerKeys.size
innerInvalidate()
- myComposer.expectNoChanges()
+ result.expectNoChanges()
assertNotEquals(previousInnerKeysSize, innerKeys.size)
assertNotEquals(innerKeys[0], outerKeys[0])
@@ -1900,7 +1901,7 @@
}
}
- val myComposer = compose {
+ val result = compose {
test()
}
@@ -1909,7 +1910,7 @@
items[3] = 2
invalidateComposition()
- myComposer.expectChanges()
+ result.expectChanges()
}
@Test // b/154650546
@@ -1985,12 +1986,12 @@
}
}
- val myComposition = compose {
+ val result = compose {
test()
}
fun validate() {
- validate(myComposition.root) {
+ result.validate {
test()
}
}
@@ -2006,7 +2007,7 @@
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
}
@@ -2052,19 +2053,19 @@
}
}
- val myComposition = compose {
+ val result = compose {
test()
}
- validate(myComposition.root) {
+ result.validate {
test()
}
items.add(2 to listOf(3, 4, 5, 6))
invalidateComposition()
- myComposition.expectChanges()
- validate(myComposition.root) {
+ result.expectChanges()
+ result.validate {
test()
}
}
@@ -2158,12 +2159,12 @@
}
}
- val myComposition = compose {
+ val result = compose {
test()
}
fun validate() {
- validate(myComposition.root) {
+ result.validate {
test()
}
}
@@ -2171,29 +2172,29 @@
includeEven = false
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
includeEven = true
includeOdd = false
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
includeEven = false
includeOdd = false
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
includeEven = true
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
includeOdd = true
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
}
@@ -2212,11 +2213,6 @@
}
@Composable
- fun MockComposeScope.wrapper(children: @Composable () -> Unit) {
- children()
- }
-
- @Composable
fun MockComposeScope.emitText(all: Boolean) {
invalidates.add(invalidate)
for (i in order) {
@@ -2288,12 +2284,12 @@
}
}
- val myComposition = compose {
+ val result = compose {
test()
}
fun validate() {
- validate(myComposition.root) {
+ result.validate {
test()
}
}
@@ -2302,33 +2298,33 @@
order = listOf(1, 2, 4, 3)
includeEven = false
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
order = listOf(1, 4, 2, 3)
includeEven = true
includeOdd = false
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
order = listOf(3, 4, 2, 1)
includeEven = false
includeOdd = false
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
order = listOf(4, 3, 2, 1)
includeEven = true
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
order = listOf(1, 2, 3, 4)
includeOdd = true
invalidateComposition()
- myComposition.expectChanges()
+ result.expectChanges()
validate()
}
}
@@ -2345,14 +2341,36 @@
}
}
+private class CompositionResult(
+ val composer: Composer<*>,
+ val root: View
+) {
+ fun validate(block: MockViewValidator.() -> Unit) {
+ MockViewListValidator(root.children).validate(block)
+ }
+
+ fun expectNoChanges() {
+ val changes = composer.recompose() && composer.changeCount > 0
+ assertFalse(changes)
+ }
+
+ fun expectChanges() {
+ val changes = composer.recompose() && composer.changeCount > 0
+ assertTrue(changes, "Expected changes")
+ composer.applyChanges()
+ composer.slotTable.verifyWellFormed()
+ }
+
+ fun recompose(): Boolean = composer.recompose()
+}
+
private fun compose(
block: @Composable MockComposeScope.() -> Unit
-): MockViewComposer {
+): CompositionResult {
+ val root = View().apply { name = "root" }
val composer = run {
- val root = View().apply { name = "root" }
-
val scope = CoroutineScope(Job())
- val clock = object : CompositionFrameClock {
+ val clock = object : MonotonicFrameClock {
override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R {
// The original version of this test used a mock Recomposer
// that never successfully scheduled a frame.
@@ -2363,28 +2381,23 @@
val recomposer = Recomposer().apply {
scope.launch { runRecomposeAndApplyChanges(clock) }
}
- MockViewComposer(root, recomposer)
+ Composer(
+ SlotTable(),
+ ViewApplier(root),
+ recomposer
+ )
}
- composer.compose {
- block()
+ val mockScope = MockComposeScope()
+ composer.composeRoot {
+ invokeComposable(composer) {
+ mockScope.block()
+ }
}
composer.applyChanges()
composer.slotTable.verifyWellFormed()
- return composer
-}
-
-private fun MockViewComposer.expectNoChanges() {
- val changes = recompose() && changeCount > 0
- assertFalse(changes)
-}
-
-private fun MockViewComposer.expectChanges() {
- val changes = recompose() && changeCount > 0
- assertTrue(changes, "Expected changes")
- applyChanges()
- slotTable.verifyWellFormed()
+ return CompositionResult(composer, root)
}
// Contact test data
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt
index 15bb61d..5d24410 100644
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/MockViewValidator.kt
@@ -89,8 +89,4 @@
val hasNext = next()
assertEquals(true, hasNext)
}
-}
-
-fun validate(root: View, block: MockViewValidator.() -> Unit) {
- MockViewListValidator(root.children).validate(block)
-}
+}
\ No newline at end of file
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewApplier.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewApplier.kt
new file mode 100644
index 0000000..7ded646
--- /dev/null
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewApplier.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.mock
+
+import androidx.compose.AbstractApplier
+import androidx.compose.Composable
+import androidx.compose.ComposeCompilerApi
+import androidx.compose.Composer
+import androidx.compose.ExperimentalComposeApi
+import androidx.compose.Stable
+import androidx.compose.currentComposer
+
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+@OptIn(ExperimentalComposeApi::class)
+class ViewApplier(root: View) : AbstractApplier<View>(root) {
+ override fun insert(index: Int, instance: View) {
+ current.addAt(index, instance)
+ }
+
+ override fun remove(index: Int, count: Int) {
+ current.removeAt(index, count)
+ }
+
+ override fun move(from: Int, to: Int, count: Int) {
+ current.moveAt(from, to, count)
+ }
+}
+
+@Stable
+class MockComposeScope
+
+// TODO(lmr): we should really remove this from our tests
+@Suppress("UNCHECKED_CAST")
+@OptIn(ComposeCompilerApi::class)
+@Composable
+fun <P1> MockComposeScope.memoize(
+ key: Int,
+ p1: P1,
+ block: @Composable (p1: P1) -> Unit
+) {
+ currentComposer.startGroup(key)
+ if (!currentComposer.changed(p1)) {
+ currentComposer.skipToGroupEnd()
+ } else {
+ val realFn = block as Function4<P1, Composer<*>, Int, Int, Unit>
+ realFn(p1, currentComposer, 0, 0)
+ }
+ currentComposer.endGroup()
+}
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewComposer.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewComposer.kt
deleted file mode 100644
index a5e5a30..0000000
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/ViewComposer.kt
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.mock
-
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
-import androidx.compose.Composable
-import androidx.compose.ComposeCompilerApi
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
-import androidx.compose.ExperimentalComposeApi
-import androidx.compose.InternalComposeApi
-import androidx.compose.Recomposer
-import androidx.compose.SlotTable
-import androidx.compose.Stable
-import androidx.compose.currentComposer
-import androidx.compose.invokeComposable
-
-@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
-@OptIn(ExperimentalComposeApi::class)
-object ViewApplierAdapter :
- ApplyAdapter<View> {
- override fun View.start(instance: View) {}
- override fun View.insertAt(index: Int, instance: View) = addAt(index, instance)
- override fun View.removeAt(index: Int, count: Int) = removeAt(index, count)
- override fun View.move(from: Int, to: Int, count: Int) = moveAt(from, to, count)
- override fun View.end(instance: View, parent: View) {}
-}
-
-typealias Updater<T> = ComposerUpdater<View, T>
-
-@Stable
-interface MockComposeScope {
- val composer: MockViewComposer
-}
-
-@OptIn(InternalComposeApi::class, ExperimentalComposeApi::class, ComposeCompilerApi::class)
-class MockViewComposer(
- val root: View,
- recomposer: Recomposer
-) : Composer<View>(SlotTable(), Applier(root, ViewApplierAdapter), recomposer), MockComposeScope {
-
- override val composer: MockViewComposer get() = this
-
- fun compose(composable: @Composable MockComposeScope.() -> Unit) {
- composeRoot {
- invokeComposable(this) {
- val c = currentComposer as MockViewComposer
- c.composable()
- }
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- inline fun <V : View> emit(
- key: Any,
- ctor: () -> V,
- update: Updater<V>.() -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor().also { emitNode(it) }
- else useNode() as V
- Updater(this, node).update()
- endNode()
- }
-
- @Suppress("UNCHECKED_CAST")
- inline fun <V : View> emit(
- key: Any,
- ctor: () -> V,
- update: Updater<V>.() -> Unit,
- children: () -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor().also { emitNode(it) }
- else useNode() as V
- Updater(this, node).update()
- children()
- endNode()
- }
-}
-
-@Suppress("UNCHECKED_CAST")
-@OptIn(ComposeCompilerApi::class)
-@Composable
-fun <P1> MockComposeScope.memoize(
- key: Int,
- p1: P1,
- block: @Composable (p1: P1) -> Unit
-) {
- with(currentComposer as MockViewComposer) {
- startGroup(key)
- if (!changed(p1)) {
- skipToGroupEnd()
- } else {
- val realFn = block as Function4<P1, Composer<*>, Int, Int, Unit>
- realFn(p1, this, 0, 0)
- }
- endGroup()
- }
-}
diff --git a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt
index 7bf8106..85fcb49c 100644
--- a/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt
+++ b/compose/compose-runtime/src/test/kotlin/androidx/compose/mock/Views.kt
@@ -17,7 +17,7 @@
package androidx.compose.mock
import androidx.compose.Composable
-import androidx.compose.currentComposer
+import androidx.compose.emit
import androidx.compose.key
@Composable
@@ -34,28 +34,38 @@
@Composable
fun MockComposeScope.linear(block: @Composable MockComposeScope.() -> Unit) {
- val c = currentComposer as MockViewComposer
- View(name = "linear") {
- c.block()
+ emit<View, ViewApplier>(
+ ctor = { View().also { it.name = "linear" } },
+ update = { }
+ ) {
+ block()
}
}
@Composable
fun MockComposeScope.text(value: String) {
- View(name = "text", text = value)
+ emit<View, ViewApplier>(
+ ctor = { View().also { it.name = "text" } },
+ update = { set(value) { text = it } }
+ )
}
@Composable
fun MockComposeScope.edit(value: String) {
- View(name = "edit", value = value)
+ emit<View, ViewApplier>(
+ ctor = { View().also { it.name = "edit" } },
+ update = { set(value) { this.value = it } }
+ )
}
@Composable
fun MockComposeScope.selectBox(selected: Boolean, block: @Composable MockComposeScope.() -> Unit) {
if (selected) {
- View(name = "box") {
- block()
- }
+ emit<View, ViewApplier>(
+ ctor = { View().also { it.name = "box" } },
+ update = { },
+ children = { block() }
+ )
} else {
block()
}
diff --git a/core/core/api/1.5.0-alpha01.txt b/core/core/api/1.5.0-alpha01.txt
index f80f458..e6df9f3 100644
--- a/core/core/api/1.5.0-alpha01.txt
+++ b/core/core/api/1.5.0-alpha01.txt
@@ -1708,10 +1708,10 @@
}
public final class PatternsCompat {
- field public static final java.util.regex.Pattern! DOMAIN_NAME;
- field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
- field public static final java.util.regex.Pattern! IP_ADDRESS;
- field public static final java.util.regex.Pattern! WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
}
public final class Pools {
diff --git a/core/core/api/api_lint.ignore b/core/core/api/api_lint.ignore
index 46772b6..b6158f8d 100644
--- a/core/core/api/api_lint.ignore
+++ b/core/core/api/api_lint.ignore
@@ -1085,14 +1085,6 @@
Missing nullability on field `LTR` in class `class androidx.core.text.TextDirectionHeuristicsCompat`
MissingNullability: androidx.core.text.TextDirectionHeuristicsCompat#RTL:
Missing nullability on field `RTL` in class `class androidx.core.text.TextDirectionHeuristicsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#DOMAIN_NAME:
- Missing nullability on field `DOMAIN_NAME` in class `class androidx.core.util.PatternsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#EMAIL_ADDRESS:
- Missing nullability on field `EMAIL_ADDRESS` in class `class androidx.core.util.PatternsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#IP_ADDRESS:
- Missing nullability on field `IP_ADDRESS` in class `class androidx.core.util.PatternsCompat`
-MissingNullability: androidx.core.util.PatternsCompat#WEB_URL:
- Missing nullability on field `WEB_URL` in class `class androidx.core.util.PatternsCompat`
MissingNullability: androidx.core.view.AccessibilityDelegateCompat#dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent) parameter #0:
Missing nullability on parameter `host` in method `dispatchPopulateAccessibilityEvent`
MissingNullability: androidx.core.view.AccessibilityDelegateCompat#dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent) parameter #1:
@@ -2111,11 +2103,11 @@
Provide an explicit copy constructor instead of implementing `clone()`
-OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #0:
+OptionalBuilderConstructorArgument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #0:
Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter icon in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
-OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #1:
+OptionalBuilderConstructorArgument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #1:
Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter title in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
-OptionalBuilderConstructorAgrument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #2:
+OptionalBuilderConstructorArgument: androidx.core.app.NotificationCompat.Action.Builder#Builder(androidx.core.graphics.drawable.IconCompat, CharSequence, android.app.PendingIntent) parameter #2:
Builder constructor arguments must be mandatory (i.e. not @Nullable): parameter intent in androidx.core.app.NotificationCompat.Action.Builder(androidx.core.graphics.drawable.IconCompat icon, CharSequence title, android.app.PendingIntent intent)
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index f80f458..e6df9f3 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -1708,10 +1708,10 @@
}
public final class PatternsCompat {
- field public static final java.util.regex.Pattern! DOMAIN_NAME;
- field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
- field public static final java.util.regex.Pattern! IP_ADDRESS;
- field public static final java.util.regex.Pattern! WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
}
public final class Pools {
diff --git a/core/core/api/public_plus_experimental_1.5.0-alpha01.txt b/core/core/api/public_plus_experimental_1.5.0-alpha01.txt
index a9a4c2e..ce97204 100644
--- a/core/core/api/public_plus_experimental_1.5.0-alpha01.txt
+++ b/core/core/api/public_plus_experimental_1.5.0-alpha01.txt
@@ -1706,10 +1706,10 @@
}
public final class PatternsCompat {
- field public static final java.util.regex.Pattern! DOMAIN_NAME;
- field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
- field public static final java.util.regex.Pattern! IP_ADDRESS;
- field public static final java.util.regex.Pattern! WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
}
public final class Pools {
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index a9a4c2e..ce97204 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -1706,10 +1706,10 @@
}
public final class PatternsCompat {
- field public static final java.util.regex.Pattern! DOMAIN_NAME;
- field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
- field public static final java.util.regex.Pattern! IP_ADDRESS;
- field public static final java.util.regex.Pattern! WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
}
public final class Pools {
diff --git a/core/core/api/restricted_1.5.0-alpha01.txt b/core/core/api/restricted_1.5.0-alpha01.txt
index a3a2802..c1640ac 100644
--- a/core/core/api/restricted_1.5.0-alpha01.txt
+++ b/core/core/api/restricted_1.5.0-alpha01.txt
@@ -2051,12 +2051,12 @@
}
public final class PatternsCompat {
- field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_EMAIL_ADDRESS;
- field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_WEB_URL;
- field public static final java.util.regex.Pattern! DOMAIN_NAME;
- field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
- field public static final java.util.regex.Pattern! IP_ADDRESS;
- field public static final java.util.regex.Pattern! WEB_URL;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_EMAIL_ADDRESS;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
}
public final class Pools {
@@ -2878,7 +2878,7 @@
method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
- field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat! CONSUMED;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat CONSUMED;
}
public static final class WindowInsetsCompat.Builder {
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index a3a2802..c1640ac 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -2051,12 +2051,12 @@
}
public final class PatternsCompat {
- field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_EMAIL_ADDRESS;
- field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern! AUTOLINK_WEB_URL;
- field public static final java.util.regex.Pattern! DOMAIN_NAME;
- field public static final java.util.regex.Pattern! EMAIL_ADDRESS;
- field public static final java.util.regex.Pattern! IP_ADDRESS;
- field public static final java.util.regex.Pattern! WEB_URL;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_EMAIL_ADDRESS;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final java.util.regex.Pattern AUTOLINK_WEB_URL;
+ field public static final java.util.regex.Pattern DOMAIN_NAME;
+ field public static final java.util.regex.Pattern EMAIL_ADDRESS;
+ field public static final java.util.regex.Pattern IP_ADDRESS;
+ field public static final java.util.regex.Pattern WEB_URL;
}
public final class Pools {
@@ -2878,7 +2878,7 @@
method @Deprecated public androidx.core.view.WindowInsetsCompat replaceSystemWindowInsets(android.graphics.Rect);
method @RequiresApi(20) public android.view.WindowInsets? toWindowInsets();
method @RequiresApi(20) public static androidx.core.view.WindowInsetsCompat toWindowInsetsCompat(android.view.WindowInsets);
- field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat! CONSUMED;
+ field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final androidx.core.view.WindowInsetsCompat CONSUMED;
}
public static final class WindowInsetsCompat.Builder {
diff --git a/datastore/datastore-preferences/api/1.0.0-alpha01.txt b/datastore/datastore-preferences/api/1.0.0-alpha01.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/1.0.0-alpha01.txt
+++ b/datastore/datastore-preferences/api/1.0.0-alpha01.txt
@@ -19,7 +19,7 @@
method public String getString(String key, String defaultValue);
method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
method public androidx.datastore.preferences.Preferences.Builder toBuilder();
- field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+ field public static final androidx.datastore.preferences.Preferences.Companion Companion;
}
public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
public final class SharedPreferencesMigration {
method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
- field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+ field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
}
public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/current.txt b/datastore/datastore-preferences/api/current.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/current.txt
+++ b/datastore/datastore-preferences/api/current.txt
@@ -19,7 +19,7 @@
method public String getString(String key, String defaultValue);
method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
method public androidx.datastore.preferences.Preferences.Builder toBuilder();
- field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+ field public static final androidx.datastore.preferences.Preferences.Companion Companion;
}
public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
public final class SharedPreferencesMigration {
method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
- field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+ field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
}
public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt b/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/datastore/datastore-preferences/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -19,7 +19,7 @@
method public String getString(String key, String defaultValue);
method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
method public androidx.datastore.preferences.Preferences.Builder toBuilder();
- field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+ field public static final androidx.datastore.preferences.Preferences.Companion Companion;
}
public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
public final class SharedPreferencesMigration {
method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
- field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+ field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
}
public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/public_plus_experimental_current.txt b/datastore/datastore-preferences/api/public_plus_experimental_current.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/public_plus_experimental_current.txt
+++ b/datastore/datastore-preferences/api/public_plus_experimental_current.txt
@@ -19,7 +19,7 @@
method public String getString(String key, String defaultValue);
method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
method public androidx.datastore.preferences.Preferences.Builder toBuilder();
- field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+ field public static final androidx.datastore.preferences.Preferences.Companion Companion;
}
public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
public final class SharedPreferencesMigration {
method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
- field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+ field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
}
public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt b/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt
+++ b/datastore/datastore-preferences/api/restricted_1.0.0-alpha01.txt
@@ -19,7 +19,7 @@
method public String getString(String key, String defaultValue);
method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
method public androidx.datastore.preferences.Preferences.Builder toBuilder();
- field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+ field public static final androidx.datastore.preferences.Preferences.Companion Companion;
}
public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
public final class SharedPreferencesMigration {
method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
- field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+ field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
}
public static final class SharedPreferencesMigration.Companion {
diff --git a/datastore/datastore-preferences/api/restricted_current.txt b/datastore/datastore-preferences/api/restricted_current.txt
index 45ea06f..7d90845 100644
--- a/datastore/datastore-preferences/api/restricted_current.txt
+++ b/datastore/datastore-preferences/api/restricted_current.txt
@@ -19,7 +19,7 @@
method public String getString(String key, String defaultValue);
method public java.util.Set<java.lang.String> getStringSet(String key, java.util.Set<java.lang.String> defaultValue);
method public androidx.datastore.preferences.Preferences.Builder toBuilder();
- field public static final androidx.datastore.preferences.Preferences.Companion! Companion;
+ field public static final androidx.datastore.preferences.Preferences.Companion Companion;
}
public static final class Preferences.Builder {
@@ -41,7 +41,7 @@
public final class SharedPreferencesMigration {
method public static kotlin.jvm.functions.Function0<androidx.datastore.DataMigration<androidx.datastore.preferences.Preferences>> create(android.content.Context context, String sharedPreferencesName, java.util.Set<java.lang.String>? keysToMigrate = MIGRATE_ALL_KEYS, boolean deleteEmptyPreferences = true);
- field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion! Companion;
+ field public static final androidx.datastore.preferences.SharedPreferencesMigration.Companion Companion;
}
public static final class SharedPreferencesMigration.Companion {
diff --git a/development/build_log_simplifier.py b/development/build_log_simplifier.py
index b7f5cf2..4f838e4 100755
--- a/development/build_log_simplifier.py
+++ b/development/build_log_simplifier.py
@@ -74,10 +74,12 @@
"A fine-grained performance profile is available: use the --scan option.",
"* Get more help at https://help.gradle.org",
"Use '--warning-mode all' to show the individual deprecation warnings.",
- "See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings"
+ "See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings",
"Note: Some input files use or override a deprecated API.",
- "Note: Recompile with -Xlint:deprecation for details."
+ "Note: Recompile with -Xlint:deprecation for details.",
+ "Note: Some input files use unchecked or unsafe operations.",
+ "Note: Recompile with -Xlint:unchecked for details."
}
skipPrefixes = [
"See the profiling report at:",
diff --git a/development/referenceDocs/stageComposeReferenceDocs.sh b/development/referenceDocs/stageComposeReferenceDocs.sh
index 95db2ae..d3c1831 100755
--- a/development/referenceDocs/stageComposeReferenceDocs.sh
+++ b/development/referenceDocs/stageComposeReferenceDocs.sh
@@ -93,7 +93,7 @@
g4d -f androidx-ref-docs-stage && \
cd third_party/devsite/android/en/reference && \
g4 sync && \
-cp -r $newDir/reference/* . && \
+cp -r $(pwd)/* . && \
/google/data/ro/projects/devsite/two/live/devsite2.par stage kotlin/androidx
\`\`\`\n"
diff --git a/fragment/fragment-testing/api/1.3.0-alpha07.txt b/fragment/fragment-testing/api/1.3.0-alpha07.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/1.3.0-alpha07.txt
+++ b/fragment/fragment-testing/api/1.3.0-alpha07.txt
@@ -6,10 +6,12 @@
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
public final class FragmentScenarioKt {
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
}
diff --git a/fragment/fragment-testing/api/api_lint.ignore b/fragment/fragment-testing/api/api_lint.ignore
index 5f4e236..eb23956 100644
--- a/fragment/fragment-testing/api/api_lint.ignore
+++ b/fragment/fragment-testing/api/api_lint.ignore
@@ -1,9 +1,17 @@
// Baseline format: 1.0
MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
Missing nullability on method `launchFragment` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory):
+ Missing nullability on method `launchFragment` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, kotlin.jvm.functions.Function0<? extends F>):
+ Missing nullability on method `launchFragment` return
MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragment(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
Missing nullability on method `launchFragment` return
MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.fragment.app.FragmentFactory):
Missing nullability on method `launchFragmentInContainer` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory):
+ Missing nullability on method `launchFragmentInContainer` return
+MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, androidx.lifecycle.Lifecycle.State, kotlin.jvm.functions.Function0<? extends F>):
+ Missing nullability on method `launchFragmentInContainer` return
MissingNullability: androidx.fragment.app.testing.FragmentScenarioKt#launchFragmentInContainer(android.os.Bundle, int, kotlin.jvm.functions.Function0<? extends F>):
Missing nullability on method `launchFragmentInContainer` return
diff --git a/fragment/fragment-testing/api/current.txt b/fragment/fragment-testing/api/current.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/current.txt
+++ b/fragment/fragment-testing/api/current.txt
@@ -6,10 +6,12 @@
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
public final class FragmentScenarioKt {
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
}
diff --git a/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt b/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt
+++ b/fragment/fragment-testing/api/public_plus_experimental_1.3.0-alpha07.txt
@@ -6,10 +6,12 @@
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
public final class FragmentScenarioKt {
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
}
diff --git a/fragment/fragment-testing/api/public_plus_experimental_current.txt b/fragment/fragment-testing/api/public_plus_experimental_current.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/public_plus_experimental_current.txt
+++ b/fragment/fragment-testing/api/public_plus_experimental_current.txt
@@ -6,10 +6,12 @@
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
public final class FragmentScenarioKt {
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
}
diff --git a/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt b/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt
+++ b/fragment/fragment-testing/api/restricted_1.3.0-alpha07.txt
@@ -6,10 +6,12 @@
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
public final class FragmentScenarioKt {
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
}
diff --git a/fragment/fragment-testing/api/restricted_current.txt b/fragment/fragment-testing/api/restricted_current.txt
index 2932e93..c3e223b 100644
--- a/fragment/fragment-testing/api/restricted_current.txt
+++ b/fragment/fragment-testing/api/restricted_current.txt
@@ -6,10 +6,12 @@
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launch(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, androidx.fragment.app.FragmentFactory?);
method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.fragment.app.FragmentFactory?);
+ method public static <F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F!> launchInContainer(Class<F!>, android.os.Bundle?, @StyleRes int, androidx.lifecycle.Lifecycle.State, androidx.fragment.app.FragmentFactory?);
method public androidx.fragment.app.testing.FragmentScenario<F!> moveToState(androidx.lifecycle.Lifecycle.State);
method public androidx.fragment.app.testing.FragmentScenario<F!> onFragment(androidx.fragment.app.testing.FragmentScenario.FragmentAction<F!>);
method public androidx.fragment.app.testing.FragmentScenario<F!> recreate();
@@ -22,8 +24,12 @@
public final class FragmentScenarioKt {
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragment(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.fragment.app.FragmentFactory? factory = null);
method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, kotlin.jvm.functions.Function0<? extends F> instantiate);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, androidx.fragment.app.FragmentFactory? factory = null);
+ method public static inline <reified F extends androidx.fragment.app.Fragment> androidx.fragment.app.testing.FragmentScenario<F>! launchFragmentInContainer(android.os.Bundle? fragmentArgs = null, @StyleRes int themeResId = androidx.fragment.testing.R.style.FragmentScenarioEmptyFragmentActivityTheme, androidx.lifecycle.Lifecycle.State initialState = androidx.lifecycle.Lifecycle.State.RESUMED, kotlin.jvm.functions.Function0<? extends F> instantiate);
method public static inline <reified F extends androidx.fragment.app.Fragment, T> T! withFragment(androidx.fragment.app.testing.FragmentScenario<F>, kotlin.jvm.functions.Function1<? super F,? extends T> block);
}
diff --git a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt
index 0b27dd8..b11604f 100644
--- a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt
+++ b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioDialogFragmentTest.kt
@@ -106,8 +106,7 @@
@Test
fun fromCreatedToCreated() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
moveToState(State.CREATED)
onFragment { fragment ->
assertThat(fragment.lifecycle.currentState).isEqualTo(State.CREATED)
@@ -120,8 +119,7 @@
@Test
fun fromCreatedToStarted() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
moveToState(State.STARTED)
onFragment { fragment ->
assertThat(fragment.lifecycle.currentState).isEqualTo(State.STARTED)
@@ -133,8 +131,7 @@
@Test
fun fromCreatedToResumed() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
moveToState(State.RESUMED)
onFragment { fragment ->
assertThat(fragment.lifecycle.currentState).isEqualTo(State.RESUMED)
@@ -146,16 +143,14 @@
@Test
fun fromCreatedToDestroyed() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.CREATED)) {
moveToState(State.DESTROYED)
}
}
@Test
fun fromStartedToCreated() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
moveToState(State.CREATED)
onFragment { fragment ->
assertThat(fragment.lifecycle.currentState).isEqualTo(State.CREATED)
@@ -168,8 +163,7 @@
@Test
fun fromStartedToStarted() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
moveToState(State.STARTED)
onFragment { fragment ->
assertThat(fragment.lifecycle.currentState).isEqualTo(State.STARTED)
@@ -181,8 +175,7 @@
@Test
fun fromStartedToResumed() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
moveToState(State.RESUMED)
onFragment { fragment ->
assertThat(fragment.lifecycle.currentState).isEqualTo(State.RESUMED)
@@ -194,8 +187,7 @@
@Test
fun fromStartedToDestroyed() {
- with(launchFragment<SimpleDialogFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragment<SimpleDialogFragment>(initialState = State.STARTED)) {
moveToState(State.DESTROYED)
}
}
@@ -211,12 +203,11 @@
@Test
fun recreateCreatedFragment() {
var numOfInstantiation = 0
- with(launchFragment {
+ with(launchFragment(initialState = State.CREATED) {
++numOfInstantiation
SimpleDialogFragment()
}) {
assertThat(numOfInstantiation).isEqualTo(1)
- moveToState(State.CREATED)
recreate()
assertThat(numOfInstantiation).isEqualTo(2)
onFragment { fragment ->
@@ -231,12 +222,11 @@
@Test
fun recreateStartedFragment() {
var numOfInstantiation = 0
- with(launchFragment {
+ with(launchFragment(initialState = State.STARTED) {
++numOfInstantiation
SimpleDialogFragment()
}) {
assertThat(numOfInstantiation).isEqualTo(1)
- moveToState(State.STARTED)
recreate()
assertThat(numOfInstantiation).isEqualTo(2)
onFragment { fragment ->
diff --git a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
index 80534a4..6d46dce 100644
--- a/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
+++ b/fragment/fragment-testing/src/androidTest/java/androidx/fragment/app/testing/FragmentScenarioTest.kt
@@ -283,8 +283,7 @@
@Test
fun fromCreatedToCreated() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
moveToState(State.CREATED)
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.CREATED)
@@ -295,8 +294,7 @@
@Test
fun fromCreatedToStarted() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
moveToState(State.STARTED)
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.STARTED)
@@ -307,8 +305,7 @@
@Test
fun fromCreatedToResumed() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
moveToState(State.RESUMED)
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.RESUMED)
@@ -319,16 +316,14 @@
@Test
fun fromCreatedToDestroyed() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
moveToState(State.DESTROYED)
}
}
@Test
fun fromStartedToCreated() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
moveToState(State.CREATED)
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.CREATED)
@@ -339,8 +334,7 @@
@Test
fun fromStartedToStarted() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
moveToState(State.STARTED)
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.STARTED)
@@ -351,8 +345,7 @@
@Test
fun fromStartedToResumed() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
moveToState(State.RESUMED)
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.RESUMED)
@@ -363,8 +356,7 @@
@Test
fun fromStartedToDestroyed() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
moveToState(State.DESTROYED)
}
}
@@ -379,8 +371,7 @@
@Test
fun recreateCreatedFragment() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.CREATED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.CREATED)) {
recreate()
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.CREATED)
@@ -391,8 +382,7 @@
@Test
fun recreateStartedFragment() {
- with(launchFragmentInContainer<StateRecordingFragment>()) {
- moveToState(State.STARTED)
+ with(launchFragmentInContainer<StateRecordingFragment>(initialState = State.STARTED)) {
recreate()
onFragment { fragment ->
assertThat(fragment.state).isEqualTo(State.STARTED)
diff --git a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java
index 206f7cc..64ff90b 100644
--- a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java
+++ b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.java
@@ -36,6 +36,7 @@
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.testing.R;
+import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Lifecycle.State;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
@@ -209,7 +210,31 @@
public static <F extends Fragment> FragmentScenario<F> launch(
@NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
@StyleRes int themeResId, @Nullable FragmentFactory factory) {
- return internalLaunch(fragmentClass, fragmentArgs, themeResId, factory,
+ return launch(fragmentClass, fragmentArgs, themeResId, Lifecycle.State.RESUMED,
+ factory);
+ }
+
+ /**
+ * Launches a Fragment with given arguments hosted by an empty {@link FragmentActivity} themed
+ * by {@code themeResId}, using the given {@link FragmentFactory} and waits for it to reach
+ * {@code initialState}.
+ * <p>
+ * This method cannot be called from the main thread.
+ *
+ * @param fragmentClass a fragment class to instantiate
+ * @param fragmentArgs a bundle to passed into fragment
+ * @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState The initial {@link Lifecycle.State}. This must be one of
+ * {@link State#CREATED CREATED}, {@link State#STARTED STARTED}, and
+ * {@link State#RESUMED RESUMED}.
+ * @param factory a fragment factory to use or null to use default factory
+ */
+ @NonNull
+ public static <F extends Fragment> FragmentScenario<F> launch(
+ @NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
+ @StyleRes int themeResId, @NonNull Lifecycle.State initialState,
+ @Nullable FragmentFactory factory) {
+ return internalLaunch(fragmentClass, fragmentArgs, themeResId, initialState, factory,
/*containerViewId=*/ 0);
}
@@ -278,15 +303,41 @@
public static <F extends Fragment> FragmentScenario<F> launchInContainer(
@NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
@StyleRes int themeResId, @Nullable FragmentFactory factory) {
+ return launchInContainer(fragmentClass, fragmentArgs, themeResId, Lifecycle.State.RESUMED,
+ factory);
+ }
+
+ /**
+ * Launches a Fragment in the Activity's root view container {@code android.R.id.content}, with
+ * given arguments hosted by an empty {@link FragmentActivity} themed by {@code themeResId},
+ * using the given {@link FragmentFactory} and waits for it to reach {@code initialState}.
+ * <p>
+ * This method cannot be called from the main thread.
+ *
+ * @param fragmentClass a fragment class to instantiate
+ * @param fragmentArgs a bundle to passed into fragment
+ * @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState The initial {@link Lifecycle.State}. This must be one of
+ * {@link State#CREATED CREATED}, {@link State#STARTED STARTED}, and
+ * {@link State#RESUMED RESUMED}.
+ * @param factory a fragment factory to use or null to use default factory
+ */
+ @NonNull
+ public static <F extends Fragment> FragmentScenario<F> launchInContainer(
+ @NonNull Class<F> fragmentClass, @Nullable Bundle fragmentArgs,
+ @StyleRes int themeResId, @NonNull Lifecycle.State initialState,
+ @Nullable FragmentFactory factory) {
return internalLaunch(
- fragmentClass, fragmentArgs, themeResId, factory, android.R.id.content);
+ fragmentClass, fragmentArgs, themeResId, initialState, factory,
+ android.R.id.content);
}
@NonNull
@SuppressLint("RestrictedApi")
private static <F extends Fragment> FragmentScenario<F> internalLaunch(
@NonNull final Class<F> fragmentClass, final @Nullable Bundle fragmentArgs,
- @StyleRes int themeResId, @Nullable final FragmentFactory factory,
+ @StyleRes int themeResId, @NonNull Lifecycle.State initialState,
+ @Nullable final FragmentFactory factory,
@IdRes final int containerViewId) {
Intent startActivityIntent =
Intent.makeMainActivity(
@@ -310,6 +361,7 @@
activity.getSupportFragmentManager()
.beginTransaction()
.add(containerViewId, fragment, FRAGMENT_TAG)
+ .setMaxLifecycle(fragment, initialState)
.commitNow();
});
return scenario;
diff --git a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
index 4766100..0854cfa 100644
--- a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
+++ b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
@@ -22,74 +22,122 @@
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentFactory
import androidx.fragment.testing.R
+import androidx.lifecycle.Lifecycle
+
+@Deprecated("Superseded by launchFragment that takes an initialState",
+ level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragment(
+ fragmentArgs: Bundle? = null,
+ @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ factory: FragmentFactory? = null
+) = launchFragment<F>(fragmentArgs, themeResId, Lifecycle.State.RESUMED, factory)
+
+@Deprecated("Superseded by launchFragment that takes an initialState",
+ level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragment(
+ fragmentArgs: Bundle? = null,
+ @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ crossinline instantiate: () -> F
+) = launchFragment(fragmentArgs, themeResId) {
+ instantiate()
+}
+
+@Deprecated("Superseded by launchFragmentInContainer that takes an initialState",
+ level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragmentInContainer(
+ fragmentArgs: Bundle? = null,
+ @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ factory: FragmentFactory? = null
+) = launchFragmentInContainer<F>(fragmentArgs, themeResId, Lifecycle.State.RESUMED, factory)
+
+@Deprecated("Superseded by launchFragmentInContainer that takes an initialState",
+ level = DeprecationLevel.HIDDEN) // Binary API compatibility.
+inline fun <reified F : Fragment> launchFragmentInContainer(
+ fragmentArgs: Bundle? = null,
+ @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ crossinline instantiate: () -> F
+) = launchFragmentInContainer(fragmentArgs, themeResId) {
+ instantiate()
+}
/**
* Launches a Fragment with given arguments hosted by an empty [FragmentActivity] using
- * given [FragmentFactory] and waits for it to reach a resumed state.
+ * given [FragmentFactory] and waits for it to reach [initialState].
*
* This method cannot be called from the main thread.
*
* @param fragmentArgs a bundle to passed into fragment
* @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
* @param factory a fragment factory to use or null to use default factory
*/
inline fun <reified F : Fragment> launchFragment(
fragmentArgs: Bundle? = null,
@StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ initialState: Lifecycle.State = Lifecycle.State.RESUMED,
factory: FragmentFactory? = null
-) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, factory)
+) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, initialState, factory)
/**
* Launches a Fragment with given arguments hosted by an empty [FragmentActivity] using
- * [instantiate] to create the Fragment and waits for it to reach a resumed state.
+ * [instantiate] to create the Fragment and waits for it to reach [initialState].
*
* This method cannot be called from the main thread.
*
* @param fragmentArgs a bundle to passed into fragment
* @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
* @param instantiate method which will be used to instantiate the Fragment.
*/
inline fun <reified F : Fragment> launchFragment(
fragmentArgs: Bundle? = null,
@StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ initialState: Lifecycle.State = Lifecycle.State.RESUMED,
crossinline instantiate: () -> F
-) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, object : FragmentFactory() {
- override fun instantiate(
- classLoader: ClassLoader,
- className: String
- ) = when (className) {
- F::class.java.name -> instantiate()
- else -> super.instantiate(classLoader, className)
- }
-})
+) = FragmentScenario.launch(F::class.java, fragmentArgs, themeResId, initialState,
+ object : FragmentFactory() {
+ override fun instantiate(
+ classLoader: ClassLoader,
+ className: String
+ ) = when (className) {
+ F::class.java.name -> instantiate()
+ else -> super.instantiate(classLoader, className)
+ }
+ })
/**
* Launches a Fragment in the Activity's root view container `android.R.id.content`, with
- * given arguments hosted by an empty [FragmentActivity] and waits for it to reach a
- * resumed state.
+ * given arguments hosted by an empty [FragmentActivity] and waits for it to reach [initialState].
*
* This method cannot be called from the main thread.
*
* @param fragmentArgs a bundle to passed into fragment
* @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
* @param factory a fragment factory to use or null to use default factory
*/
inline fun <reified F : Fragment> launchFragmentInContainer(
fragmentArgs: Bundle? = null,
@StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ initialState: Lifecycle.State = Lifecycle.State.RESUMED,
factory: FragmentFactory? = null
-) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId, factory)
+) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId, initialState,
+ factory)
/**
* Launches a Fragment in the Activity's root view container `android.R.id.content`, with
* given arguments hosted by an empty [FragmentActivity] using
- * [instantiate] to create the Fragment and waits for it to reach a
- * resumed state.
+ * [instantiate] to create the Fragment and waits for it to reach [initialState].
*
* This method cannot be called from the main thread.
*
* @param fragmentArgs a bundle to passed into fragment
* @param themeResId a style resource id to be set to the host activity's theme
+ * @param initialState the initial [Lifecycle.State]. This must be one of
+ * [Lifecycle.State.CREATED], [Lifecycle.State.STARTED], or [Lifecycle.State.RESUMED].
* @param instantiate method which will be used to instantiate the Fragment. This is a
* simplification of the [FragmentFactory] interface for cases where only a single class
* needs a custom constructor called.
@@ -97,8 +145,9 @@
inline fun <reified F : Fragment> launchFragmentInContainer(
fragmentArgs: Bundle? = null,
@StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
+ initialState: Lifecycle.State = Lifecycle.State.RESUMED,
crossinline instantiate: () -> F
-) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId,
+) = FragmentScenario.launchInContainer(F::class.java, fragmentArgs, themeResId, initialState,
object : FragmentFactory() {
override fun instantiate(
classLoader: ClassLoader,
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
index 11f56ca..cc758d9 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
@@ -144,6 +144,92 @@
}
@Test
+ fun testClearResultListenerInCallback() {
+ with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+ val fm = withActivity {
+ setContentView(R.layout.simple_container)
+ supportFragmentManager
+ }
+
+ val fragment1 = ClearResultFragment()
+
+ // set a result while no listener is available so it is stored in the fragment manager
+ fm.setFragmentResult("requestKey", Bundle())
+
+ // adding the fragment is going to execute and clear its listener.
+ withActivity {
+ fm.beginTransaction()
+ .add(R.id.fragmentContainer, fragment1)
+ .commitNow()
+ }
+
+ // lets set another listener with the same key as the original
+ fm.setFragmentResultListener("requestKey", fragment1,
+ FragmentResultListener { _, _ -> })
+
+ // do a replace to force the lifecycle back below STARTED
+ fm.beginTransaction()
+ .replace(R.id.fragmentContainer, StrictFragment())
+ .addToBackStack(null)
+ .commit()
+ executePendingTransactions()
+
+ // store the result in the fragment manager since no listener is available
+ fm.setFragmentResult("requestKey", Bundle())
+
+ // pop the back stack to execute the new listener
+ withActivity {
+ fm.popBackStackImmediate()
+ }
+
+ assertWithMessage("the first listener should only be executed once")
+ .that(fragment1.callbackCount).isEqualTo(1)
+ }
+ }
+
+ @Test
+ fun testResetResultListener() {
+ with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+ val fm = withActivity {
+ setContentView(R.layout.simple_container)
+ supportFragmentManager
+ }
+
+ var firstListenerFired = false
+ var secondListenerFired = false
+
+ val fragment1 = StrictFragment()
+
+ // set a listener
+ fm.setFragmentResultListener("requestKey", fragment1,
+ FragmentResultListener { _, _ ->
+ firstListenerFired = true
+ })
+
+ // lets set another listener before the first is fired
+ fm.setFragmentResultListener("requestKey", fragment1,
+ FragmentResultListener { _, _ ->
+ secondListenerFired = true
+ })
+
+ // set a result while no listener is available so it is stored in the fragment manager
+ fm.setFragmentResult("requestKey", Bundle())
+
+ // adding the fragment is going to execute the listener's callback
+ withActivity {
+ fm.beginTransaction()
+ .add(R.id.fragmentContainer, fragment1)
+ .commitNow()
+ }
+
+ assertWithMessage("the first listener should never be executed")
+ .that(firstListenerFired).isFalse()
+ assertWithMessage("the second listener should have be executed")
+ .that(secondListenerFired).isTrue()
+ }
+ }
+
+ @Test
fun testSetResultWhileResumed() {
with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
val fm = withActivity {
@@ -293,6 +379,20 @@
}
}
+class ClearResultFragment : StrictFragment() {
+ var callbackCount = 0
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ parentFragmentManager.setFragmentResultListener("requestKey", this,
+ FragmentResultListener { _, _ ->
+ callbackCount++
+ parentFragmentManager.clearFragmentResultListener("requestKey")
+ })
+ }
+}
+
class ParentResultFragment : StrictFragment() {
var actualResult: String? = null
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index 39592ff..18dd954a 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -210,11 +210,14 @@
private static class LifecycleAwareResultListener implements FragmentResultListener {
private final Lifecycle mLifecycle;
private final FragmentResultListener mListener;
+ private final LifecycleEventObserver mObserver;
LifecycleAwareResultListener(@NonNull Lifecycle lifecycle,
- @NonNull FragmentResultListener listener) {
+ @NonNull FragmentResultListener listener,
+ @NonNull LifecycleEventObserver observer) {
mLifecycle = lifecycle;
mListener = listener;
+ mObserver = observer;
}
public boolean isAtLeast(Lifecycle.State state) {
@@ -225,6 +228,10 @@
public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle result) {
mListener.onFragmentResult(requestKey, result);
}
+
+ public void removeObserver() {
+ mLifecycle.removeObserver(mObserver);
+ }
}
/**
@@ -871,12 +878,19 @@
}
};
lifecycle.addObserver(observer);
- mResultListeners.put(requestKey, new LifecycleAwareResultListener(lifecycle, listener));
+ LifecycleAwareResultListener storedListener = mResultListeners.put(requestKey,
+ new LifecycleAwareResultListener(lifecycle, listener, observer));
+ if (storedListener != null) {
+ storedListener.removeObserver();
+ }
}
@Override
public final void clearFragmentResultListener(@NonNull String requestKey) {
- mResultListeners.remove(requestKey);
+ LifecycleAwareResultListener listener = mResultListeners.remove(requestKey);
+ if (listener != null) {
+ listener.removeObserver();
+ }
}
/**
diff --git a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
index 58b8625..711bb2c 100644
--- a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
+++ b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
@@ -62,7 +62,7 @@
@Override
@NonNull
- public MyViewModel create(@NonNull SavedStateHandle arg0) {
+ public MyViewModel create(SavedStateHandle arg0) {
return new MyViewModel();
}
}
@@ -112,7 +112,7 @@
@Override
@NonNull
- public MyViewModel create(@NonNull SavedStateHandle arg0) {
+ public MyViewModel create(SavedStateHandle arg0) {
return new MyViewModel(arg0);
}
}
@@ -180,7 +180,7 @@
@Override
@NonNull
- public MyViewModel create(@NonNull SavedStateHandle arg0) {
+ public MyViewModel create(SavedStateHandle arg0) {
return new MyViewModel(s.get(), f.get(), arg0, l.get());
}
}
@@ -246,7 +246,7 @@
@Override
@NonNull
- public MyViewModel create(@NonNull SavedStateHandle arg0) {
+ public MyViewModel create(SavedStateHandle arg0) {
return new MyViewModel(s.get(), f, arg0);
}
}
@@ -322,7 +322,7 @@
@Override
@NonNull
- public MyViewModel create(@NonNull SavedStateHandle arg0) {
+ public MyViewModel create(SavedStateHandle arg0) {
return new MyViewModel(s.get(), l, arg0);
}
}
@@ -421,7 +421,7 @@
@Override
@NonNull
- public Outer.InnerViewModel create(@NonNull SavedStateHandle arg0) {
+ public Outer.InnerViewModel create(SavedStateHandle arg0) {
return new Outer.InnerViewModel();
}
}
diff --git a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt
index c5360b4..371e533 100644
--- a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt
+++ b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/work/WorkerGeneratorTest.kt
@@ -87,7 +87,7 @@
@Override
@NonNull
- public MyWorker create(@NonNull Context arg0, @NonNull WorkerParameters arg1) {
+ public MyWorker create(Context arg0, WorkerParameters arg1) {
return new MyWorker(arg0, arg1, s.get(), f.get(), l.get());
}
}
diff --git a/jetifier/jetifier/migration.config b/jetifier/jetifier/migration.config
index a39738b..0e7bb80 100644
--- a/jetifier/jetifier/migration.config
+++ b/jetifier/jetifier/migration.config
@@ -302,13 +302,85 @@
"slRules": [
{
"from": "androidx/core/view/inputmethod/(.*)",
- "to": "android/support/v13/view/inputmethod/{0}"
+ "to": "ignore"
},
{
"from": "androidx/core/content/ContextCompat(.*)",
"to": "ignore"
},
{
+ "from": "androidx/core/app/Person(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/math/MathUtils(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/net/(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/provider/(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/text/util/(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/text/(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/JobIntentService(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/accessibilityservice/AccessibilityServiceInfoCompat(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/ActivityCompat(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/ActivityManagerCompat(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/ActivityOptionsCompat(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/ActivityRecreator(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/AlarmManagerCompat(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/AppComponentFactory(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/AppLaunchChecker(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/AppOpsManagerCompat(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/app/CoreComponentFactory(.*)",
+ "to": "ignore"
+ },
+ {
+ "from": "androidx/core/os/(.*)",
+ "to": "ignore"
+ },
+ {
"from": "androidx/viewpager2/(.*)",
"to": "ignore"
},
@@ -3779,18 +3851,9 @@
"android/support/multidex/MultiDexApplication": "androidx/multidex/MultiDexApplication",
"android/support/multidex/MultiDexExtractor": "androidx/multidex/MultiDexExtractor",
"android/support/multidex/ZipUtil": "androidx/multidex/ZipUtil",
- "android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat": "androidx/core/accessibilityservice/AccessibilityServiceInfoCompat",
- "android/support/v4/app/ActivityCompat": "androidx/core/app/ActivityCompat",
- "android/support/v4/app/ActivityManagerCompat": "androidx/core/app/ActivityManagerCompat",
- "android/support/v4/app/ActivityOptionsCompat": "androidx/core/app/ActivityOptionsCompat",
- "android/support/v4/app/AlarmManagerCompat": "androidx/core/app/AlarmManagerCompat",
- "android/support/v4/app/AppComponentFactory": "androidx/core/app/AppComponentFactory",
- "android/support/v4/app/AppLaunchChecker": "androidx/core/app/AppLaunchChecker",
- "android/support/v4/app/AppOpsManagerCompat": "androidx/core/app/AppOpsManagerCompat",
"android/support/v4/app/BackStackRecord": "androidx/fragment/app/BackStackRecord",
"android/support/v4/app/BackStackState": "androidx/fragment/app/BackStackState",
"android/support/v4/app/BundleCompat": "androidx/core/app/BundleCompat",
- "android/support/v4/app/CoreComponentFactory": "androidx/core/app/CoreComponentFactory",
"android/support/v4/app/DialogFragment": "androidx/fragment/app/DialogFragment",
"android/support/v4/app/Fragment": "androidx/fragment/app/Fragment",
"android/support/v4/app/FragmentActivity": "androidx/fragment/app/FragmentActivity",
@@ -3811,7 +3874,6 @@
"android/support/v4/app/FragmentTransitionImpl": "androidx/fragment/app/FragmentTransitionImpl",
"android/support/v4/app/FrameMetricsAggregator": "androidx/core/app/FrameMetricsAggregator",
"android/support/v4/app/INotificationSideChannel": "androidx/core/app/INotificationSideChannel",
- "android/support/v4/app/JobIntentService": "androidx/core/app/JobIntentService",
"android/support/v4/app/ListFragment": "androidx/fragment/app/ListFragment",
"android/support/v4/app/NavUtils": "androidx/core/app/NavUtils",
"android/support/v4/app/NotificationBuilderWithBuilderAccessor": "androidx/core/app/NotificationBuilderWithBuilderAccessor",
@@ -3822,7 +3884,6 @@
"android/support/v4/app/NotificationCompatSideChannelService": "androidx/core/app/NotificationCompatSideChannelService",
"android/support/v4/app/NotificationManagerCompat": "androidx/core/app/NotificationManagerCompat",
"android/support/v4/app/OneShotPreDrawListener": "androidx/fragment/app/OneShotPreDrawListener",
- "android/support/v4/app/Person": "androidx/core/app/Person",
"android/support/v4/app/RemoteInput": "androidx/core/app/RemoteInput",
"android/support/v4/app/ServiceCompat": "androidx/core/app/ServiceCompat",
"android/support/v4/app/ShareCompat": "androidx/core/app/ShareCompat",
@@ -3881,39 +3942,6 @@
"android/support/v4/internal/view/SupportMenu": "androidx/core/internal/view/SupportMenu",
"android/support/v4/internal/view/SupportMenuItem": "androidx/core/internal/view/SupportMenuItem",
"android/support/v4/internal/view/SupportSubMenu": "androidx/core/internal/view/SupportSubMenu",
- "android/support/v4/math/MathUtils": "androidx/core/math/MathUtils",
- "android/support/v4/net/ConnectivityManagerCompat": "androidx/core/net/ConnectivityManagerCompat",
- "android/support/v4/net/DatagramSocketWrapper": "androidx/core/net/DatagramSocketWrapper",
- "android/support/v4/net/TrafficStatsCompat": "androidx/core/net/TrafficStatsCompat",
- "android/support/v4/os/BuildCompat": "androidx/core/os/BuildCompat",
- "android/support/v4/os/CancellationSignal": "androidx/core/os/CancellationSignal",
- "android/support/v4/os/ConfigurationCompat": "androidx/core/os/ConfigurationCompat",
- "android/support/v4/os/EnvironmentCompat": "androidx/core/os/EnvironmentCompat",
- "android/support/v4/os/HandlerCompat": "androidx/core/os/HandlerCompat",
- "android/support/v4/os/IResultReceiver": "androidx/core/os/IResultReceiver",
- "android/support/v4/os/LocaleHelper": "androidx/core/os/LocaleHelper",
- "android/support/v4/os/LocaleListCompat": "androidx/core/os/LocaleListCompat",
- "android/support/v4/os/LocaleListHelper": "androidx/core/os/LocaleListHelper",
- "android/support/v4/os/LocaleListInterface": "androidx/core/os/LocaleListInterface",
- "android/support/v4/os/OperationCanceledException": "androidx/core/os/OperationCanceledException",
- "android/support/v4/os/ParcelCompat": "androidx/core/os/ParcelCompat",
- "android/support/v4/os/ParcelableCompat": "androidx/core/os/ParcelableCompat",
- "android/support/v4/os/ParcelableCompatCreatorCallbacks": "androidx/core/os/ParcelableCompatCreatorCallbacks",
- "android/support/v4/os/ResultReceiver": "androidx/core/os/ResultReceiver",
- "android/support/v4/os/TraceCompat": "androidx/core/os/TraceCompat",
- "android/support/v4/os/UserManagerCompat": "androidx/core/os/UserManagerCompat",
- "android/support/v4/provider/FontRequest": "androidx/core/provider/FontRequest",
- "android/support/v4/provider/FontsContractCompat": "androidx/core/provider/FontsContractCompat",
- "android/support/v4/provider/SelfDestructiveThread": "androidx/core/provider/SelfDestructiveThread",
- "android/support/v4/text/BidiFormatter": "androidx/core/text/BidiFormatter",
- "android/support/v4/text/HtmlCompat": "androidx/core/text/HtmlCompat",
- "android/support/v4/text/ICUCompat": "androidx/core/text/ICUCompat",
- "android/support/v4/text/PrecomputedTextCompat": "androidx/core/text/PrecomputedTextCompat",
- "android/support/v4/text/TextDirectionHeuristicCompat": "androidx/core/text/TextDirectionHeuristicCompat",
- "android/support/v4/text/TextDirectionHeuristicsCompat": "androidx/core/text/TextDirectionHeuristicsCompat",
- "android/support/v4/text/TextUtilsCompat": "androidx/core/text/TextUtilsCompat",
- "android/support/v4/text/util/FindAddress": "androidx/core/text/util/FindAddress",
- "android/support/v4/text/util/LinkifyCompat": "androidx/core/text/util/LinkifyCompat",
"android/support/v4/util/AtomicFile": "androidx/core/util/AtomicFile",
"android/support/v4/util/Consumer": "androidx/core/util/Consumer",
"android/support/v4/util/DebugUtils": "androidx/core/util/DebugUtils",
@@ -4154,9 +4182,6 @@
"android/support/v7/widget/helper/ItemTouchUIUtil": "androidx/recyclerview/widget/ItemTouchUIUtil",
"android/support/v7/widget/helper/ItemTouchUIUtilImpl": "androidx/recyclerview/widget/ItemTouchUIUtilImpl",
"android/support/v7/widget/util/SortedListAdapterCallback": "androidx/recyclerview/widget/SortedListAdapterCallback",
- "android/support/v13/view/inputmethod/EditorInfoCompat": "androidx/core/view/inputmethod/EditorInfoCompat",
- "android/support/v13/view/inputmethod/InputConnectionCompat": "androidx/core/view/inputmethod/InputConnectionCompat",
- "android/support/v13/view/inputmethod/InputContentInfoCompat": "androidx/core/view/inputmethod/InputContentInfoCompat",
"android/viewbinding/ViewBinding": "androidx/viewbinding/ViewBinding"
}
},
diff --git a/leanback/leanback/api/1.1.0-alpha04.txt b/leanback/leanback/api/1.1.0-alpha04.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/1.1.0-alpha04.txt
+++ b/leanback/leanback/api/1.1.0-alpha04.txt
@@ -1530,7 +1530,7 @@
field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
field public static final int VIEW_TYPE_INFO = 1; // 0x1
field public static final int VIEW_TYPE_MAIN = 0; // 0x0
- field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+ field public int viewType;
}
public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/current.txt b/leanback/leanback/api/current.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/current.txt
+++ b/leanback/leanback/api/current.txt
@@ -1530,7 +1530,7 @@
field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
field public static final int VIEW_TYPE_INFO = 1; // 0x1
field public static final int VIEW_TYPE_MAIN = 0; // 0x0
- field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+ field public int viewType;
}
public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt b/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt
+++ b/leanback/leanback/api/public_plus_experimental_1.1.0-alpha04.txt
@@ -1530,7 +1530,7 @@
field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
field public static final int VIEW_TYPE_INFO = 1; // 0x1
field public static final int VIEW_TYPE_MAIN = 0; // 0x0
- field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+ field public int viewType;
}
public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/public_plus_experimental_current.txt b/leanback/leanback/api/public_plus_experimental_current.txt
index ea90aa3..733f94f 100644
--- a/leanback/leanback/api/public_plus_experimental_current.txt
+++ b/leanback/leanback/api/public_plus_experimental_current.txt
@@ -1530,7 +1530,7 @@
field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
field public static final int VIEW_TYPE_INFO = 1; // 0x1
field public static final int VIEW_TYPE_MAIN = 0; // 0x0
- field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+ field public int viewType;
}
public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/restricted_1.1.0-alpha04.txt b/leanback/leanback/api/restricted_1.1.0-alpha04.txt
index 0606e63..dc22fe8 100644
--- a/leanback/leanback/api/restricted_1.1.0-alpha04.txt
+++ b/leanback/leanback/api/restricted_1.1.0-alpha04.txt
@@ -1740,7 +1740,7 @@
field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
field public static final int VIEW_TYPE_INFO = 1; // 0x1
field public static final int VIEW_TYPE_MAIN = 0; // 0x0
- field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+ field public int viewType;
}
public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/leanback/leanback/api/restricted_current.txt b/leanback/leanback/api/restricted_current.txt
index 0606e63..dc22fe8 100644
--- a/leanback/leanback/api/restricted_current.txt
+++ b/leanback/leanback/api/restricted_current.txt
@@ -1740,7 +1740,7 @@
field public static final int VIEW_TYPE_EXTRA = 2; // 0x2
field public static final int VIEW_TYPE_INFO = 1; // 0x1
field public static final int VIEW_TYPE_MAIN = 0; // 0x0
- field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_MAIN, to="MAIN"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_INFO, to="INFO"), @android.view.ViewDebug.IntToString(from=androidx.leanback.widget.BaseCardView.LayoutParams.VIEW_TYPE_EXTRA, to="EXTRA")}) public int viewType;
+ field public int viewType;
}
public abstract class BaseGridView extends androidx.recyclerview.widget.RecyclerView {
diff --git a/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt b/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-common/api/2.3.0-alpha05.txt
@@ -9,6 +9,11 @@
}
public enum Lifecycle.Event {
+ method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+ method public androidx.lifecycle.Lifecycle.State getTargetState();
+ method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
diff --git a/lifecycle/lifecycle-common/api/current.txt b/lifecycle/lifecycle-common/api/current.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/current.txt
+++ b/lifecycle/lifecycle-common/api/current.txt
@@ -9,6 +9,11 @@
}
public enum Lifecycle.Event {
+ method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+ method public androidx.lifecycle.Lifecycle.State getTargetState();
+ method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
diff --git a/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt b/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-common/api/public_plus_experimental_2.3.0-alpha05.txt
@@ -9,6 +9,11 @@
}
public enum Lifecycle.Event {
+ method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+ method public androidx.lifecycle.Lifecycle.State getTargetState();
+ method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
diff --git a/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
index 3f2e1d7..615f457 100644
--- a/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
@@ -9,6 +9,11 @@
}
public enum Lifecycle.Event {
+ method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+ method public androidx.lifecycle.Lifecycle.State getTargetState();
+ method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
diff --git a/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt b/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt
index 0a6849f..0e3bc8a 100644
--- a/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-common/api/restricted_2.3.0-alpha05.txt
@@ -16,6 +16,11 @@
}
public enum Lifecycle.Event {
+ method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+ method public androidx.lifecycle.Lifecycle.State getTargetState();
+ method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
diff --git a/lifecycle/lifecycle-common/api/restricted_current.txt b/lifecycle/lifecycle-common/api/restricted_current.txt
index 0a6849f..0e3bc8a 100644
--- a/lifecycle/lifecycle-common/api/restricted_current.txt
+++ b/lifecycle/lifecycle-common/api/restricted_current.txt
@@ -16,6 +16,11 @@
}
public enum Lifecycle.Event {
+ method public static androidx.lifecycle.Lifecycle.Event? downFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? downTo(androidx.lifecycle.Lifecycle.State);
+ method public androidx.lifecycle.Lifecycle.State getTargetState();
+ method public static androidx.lifecycle.Lifecycle.Event? upFrom(androidx.lifecycle.Lifecycle.State);
+ method public static androidx.lifecycle.Lifecycle.Event? upTo(androidx.lifecycle.Lifecycle.State);
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_ANY;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_CREATE;
enum_constant public static final androidx.lifecycle.Lifecycle.Event ON_DESTROY;
diff --git a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java
index 78e9f92..a57e43d 100644
--- a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java
+++ b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.java
@@ -18,6 +18,7 @@
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import java.util.concurrent.atomic.AtomicReference;
@@ -153,7 +154,123 @@
/**
* An {@link Event Event} constant that can be used to match all events.
*/
- ON_ANY
+ ON_ANY;
+
+ /**
+ * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+ * leaving the specified {@link Lifecycle.State} to a lower state, or {@code null}
+ * if there is no valid event that can move down from the given state.
+ *
+ * @param state the higher state that the returned event will transition down from
+ * @return the event moving down the lifecycle phases from state
+ */
+ @Nullable
+ public static Event downFrom(@NonNull State state) {
+ switch (state) {
+ case CREATED:
+ return ON_DESTROY;
+ case STARTED:
+ return ON_STOP;
+ case RESUMED:
+ return ON_PAUSE;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+ * entering the specified {@link Lifecycle.State} from a higher state, or {@code null}
+ * if there is no valid event that can move down to the given state.
+ *
+ * @param state the lower state that the returned event will transition down to
+ * @return the event moving down the lifecycle phases to state
+ */
+ @Nullable
+ public static Event downTo(@NonNull State state) {
+ switch (state) {
+ case DESTROYED:
+ return ON_DESTROY;
+ case CREATED:
+ return ON_STOP;
+ case STARTED:
+ return ON_PAUSE;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+ * leaving the specified {@link Lifecycle.State} to a higher state, or {@code null}
+ * if there is no valid event that can move up from the given state.
+ *
+ * @param state the lower state that the returned event will transition up from
+ * @return the event moving up the lifecycle phases from state
+ */
+ @Nullable
+ public static Event upFrom(@NonNull State state) {
+ switch (state) {
+ case INITIALIZED:
+ return ON_CREATE;
+ case CREATED:
+ return ON_START;
+ case STARTED:
+ return ON_RESUME;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the {@link Lifecycle.Event} that will be reported by a {@link Lifecycle}
+ * entering the specified {@link Lifecycle.State} from a lower state, or {@code null}
+ * if there is no valid event that can move up to the given state.
+ *
+ * @param state the higher state that the returned event will transition up to
+ * @return the event moving up the lifecycle phases to state
+ */
+ @Nullable
+ public static Event upTo(@NonNull State state) {
+ switch (state) {
+ case CREATED:
+ return ON_CREATE;
+ case STARTED:
+ return ON_START;
+ case RESUMED:
+ return ON_RESUME;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the new {@link Lifecycle.State} of a {@link Lifecycle} that just reported
+ * this {@link Lifecycle.Event}.
+ *
+ * Throws {@link IllegalArgumentException} if called on {@link #ON_ANY}, as it is a special
+ * value used by {@link OnLifecycleEvent} and not a real lifecycle event.
+ *
+ * @return the state that will result from this event
+ */
+ @NonNull
+ public State getTargetState() {
+ switch (this) {
+ case ON_CREATE:
+ case ON_STOP:
+ return State.CREATED;
+ case ON_START:
+ case ON_PAUSE:
+ return State.STARTED;
+ case ON_RESUME:
+ return State.RESUMED;
+ case ON_DESTROY:
+ return State.DESTROYED;
+ case ON_ANY:
+ break;
+ }
+ throw new IllegalArgumentException(this + " has no target state");
+ }
}
/**
diff --git a/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt b/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
index eee40a8..578bd71 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
@@ -16,41 +16,55 @@
package androidx.lifecycle
+import androidx.arch.core.executor.ArchTaskExecutor
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
@RunWith(AndroidJUnit4::class)
class FlowAsLiveDataIntegrationTest {
+
+ @Before
+ fun clearArchExecutors() {
+ // make sure we don't receive a modified delegate. b/159212029
+ ArchTaskExecutor.getInstance().setDelegate(null)
+ }
+
@Test
@SmallTest
fun startStopImmediately() {
runBlocking {
- val mediator = withContext(Dispatchers.Main) {
+ val stopChannelFlow = CompletableDeferred<Unit>()
+ val (mediator, liveData) = withContext(Dispatchers.Main) {
val mediator = MediatorLiveData<Int>()
val liveData = channelFlow {
send(1)
- delay(30000) // prevent block from ending
+ // prevent block from ending
+ stopChannelFlow.await()
}.asLiveData()
mediator.addSource(liveData) {
mediator.removeSource(liveData)
mediator.value = -it
}
- mediator
+ mediator to liveData
}
val read = mediator.asFlow().first()
- Truth.assertThat(read).isEqualTo(-1)
+ assertThat(read).isEqualTo(-1)
+ assertThat(liveData.hasObservers()).isFalse()
+ // make sure this test doesn't leak a running coroutine
+ stopChannelFlow.complete(Unit)
}
}
-}
\ No newline at end of file
+}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt b/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/2.3.0-alpha05.txt
@@ -7,6 +7,10 @@
method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
}
+ public final class LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+ ctor public LifecycleDestroyedException();
+ }
+
public final class LifecycleKt {
method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
}
@@ -29,5 +33,16 @@
method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
}
+ public final class WithLifecycleStateKt {
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ }
+
}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/current.txt b/lifecycle/lifecycle-runtime-ktx/api/current.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/current.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/current.txt
@@ -7,6 +7,10 @@
method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
}
+ public final class LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+ ctor public LifecycleDestroyedException();
+ }
+
public final class LifecycleKt {
method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
}
@@ -29,5 +33,16 @@
method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
}
+ public final class WithLifecycleStateKt {
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ }
+
}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.3.0-alpha05.txt
@@ -7,6 +7,10 @@
method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
}
+ public final class LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+ ctor public LifecycleDestroyedException();
+ }
+
public final class LifecycleKt {
method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
}
@@ -29,5 +33,16 @@
method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
}
+ public final class WithLifecycleStateKt {
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ }
+
}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt
index 60b6383..2635d16 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_current.txt
@@ -7,6 +7,10 @@
method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
}
+ public final class LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+ ctor public LifecycleDestroyedException();
+ }
+
public final class LifecycleKt {
method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
}
@@ -29,5 +33,16 @@
method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
}
+ public final class WithLifecycleStateKt {
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ }
+
}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt b/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt
index 60b6383..3d7a81d 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/restricted_2.3.0-alpha05.txt
@@ -7,6 +7,10 @@
method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
}
+ public final class LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+ ctor public LifecycleDestroyedException();
+ }
+
public final class LifecycleKt {
method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
}
@@ -29,5 +33,18 @@
method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
}
+ public final class WithLifecycleStateKt {
+ method @kotlin.PublishedApi internal static suspend <R> Object? suspendWithStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, boolean dispatchNeeded, kotlinx.coroutines.CoroutineDispatcher lifecycleDispatcher, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method @kotlin.PublishedApi internal static suspend inline <R> Object? withStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ }
+
}
diff --git a/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt b/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt
index 60b6383..3d7a81d 100644
--- a/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt
+++ b/lifecycle/lifecycle-runtime-ktx/api/restricted_current.txt
@@ -7,6 +7,10 @@
method public final kotlinx.coroutines.Job launchWhenStarted(kotlin.jvm.functions.Function2<? super kotlinx.coroutines.CoroutineScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
}
+ public final class LifecycleDestroyedException extends java.util.concurrent.CancellationException {
+ ctor public LifecycleDestroyedException();
+ }
+
public final class LifecycleKt {
method public static androidx.lifecycle.LifecycleCoroutineScope getCoroutineScope(androidx.lifecycle.Lifecycle);
}
@@ -29,5 +33,18 @@
method public static androidx.lifecycle.LifecycleOwner? findViewTreeLifecycleOwner(android.view.View);
}
+ public final class WithLifecycleStateKt {
+ method @kotlin.PublishedApi internal static suspend <R> Object? suspendWithStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, boolean dispatchNeeded, kotlinx.coroutines.CoroutineDispatcher lifecycleDispatcher, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withCreated(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withResumed(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.Lifecycle, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStarted(androidx.lifecycle.LifecycleOwner, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method public static suspend inline <R> Object? withStateAtLeast(androidx.lifecycle.LifecycleOwner, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ method @kotlin.PublishedApi internal static suspend inline <R> Object? withStateAtLeastUnchecked(androidx.lifecycle.Lifecycle, androidx.lifecycle.Lifecycle.State state, kotlin.jvm.functions.Function0<? extends R> block, kotlin.coroutines.Continuation<? super R> p);
+ }
+
}
diff --git a/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/WithLifecycleStateTest.kt b/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/WithLifecycleStateTest.kt
new file mode 100644
index 0000000..fadcc5d
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/src/androidTest/java/androidx/lifecycle/WithLifecycleStateTest.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle
+
+import androidx.test.filters.SmallTest
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.yield
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+@SmallTest
+class WithLifecycleStateTest {
+ @Test
+ fun testInitialResumed() = runBlocking(Dispatchers.Main) {
+ val owner = FakeLifecycleOwner(Lifecycle.State.RESUMED)
+
+ val expected = "initial value"
+ var toRead = expected
+ launch { toRead = "value set by launch" }
+ val readByWithStarted = owner.withStarted { toRead }
+ assertEquals(expected, readByWithStarted)
+ }
+
+ @Test
+ fun testBlockRunsWithLifecycleStateChange() = runBlocking(Dispatchers.Main) {
+ val owner = FakeLifecycleOwner()
+
+ val initial = "initial value"
+ val afterSetState = "value set after setState"
+ var toRead = initial
+ launch {
+ owner.setState(Lifecycle.State.RESUMED)
+ toRead = afterSetState
+ }
+ val readByWithStarted = owner.withStarted { toRead }
+ val readAfterResumed = toRead
+ assertEquals(initial, readByWithStarted)
+ assertEquals(afterSetState, readAfterResumed)
+ }
+
+ @Test
+ fun testBlockCancelledWhenInitiallyDestroyed() = runBlocking(Dispatchers.Main) {
+ val owner = FakeLifecycleOwner(Lifecycle.State.DESTROYED)
+
+ val result = runCatching {
+ owner.withStarted {}
+ }
+
+ assertTrue("withStarted threw LifecycleDestroyedException",
+ result.exceptionOrNull() is LifecycleDestroyedException)
+ }
+
+ @Test
+ fun testBlockCancelledWhenDestroyedWhileSuspended() = runBlocking(Dispatchers.Main) {
+ val owner = FakeLifecycleOwner(Lifecycle.State.CREATED)
+
+ var launched = false
+ val resultTask = async {
+ launched = true
+ runCatching { owner.withStarted {} }
+ }
+ yield()
+
+ assertTrue("test ran to first suspension after successfully launching", launched)
+ assertTrue("withStarted is still active", resultTask.isActive)
+
+ owner.setState(Lifecycle.State.DESTROYED)
+
+ assertTrue("result threw LifecycleDestroyedException",
+ resultTask.await().exceptionOrNull() is LifecycleDestroyedException)
+ }
+}
diff --git a/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/WithLifecycleState.kt b/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/WithLifecycleState.kt
new file mode 100644
index 0000000..ac741f5
--- /dev/null
+++ b/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/WithLifecycleState.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.lifecycle
+
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlin.coroutines.coroutineContext
+import kotlin.coroutines.resumeWithException
+
+/**
+ * A [CancellationException] that indicates that the [Lifecycle] associated with an operation
+ * reached the [Lifecycle.State.DESTROYED] state before the operation could complete.
+ */
+class LifecycleDestroyedException : CancellationException()
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [state] and
+ * resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withStateAtLeast(
+ state: Lifecycle.State,
+ crossinline block: () -> R
+): R {
+ require(state >= Lifecycle.State.CREATED) {
+ "target state must be CREATED or greater, found $state"
+ }
+
+ return withStateAtLeastUnchecked(state, block)
+}
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [Lifecycle.State.CREATED]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withCreated(
+ crossinline block: () -> R
+): R = withStateAtLeastUnchecked(
+ state = Lifecycle.State.CREATED,
+ block = block
+)
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [Lifecycle.State.STARTED]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withStarted(
+ crossinline block: () -> R
+): R = withStateAtLeastUnchecked(
+ state = Lifecycle.State.STARTED,
+ block = block
+)
+
+/**
+ * Run [block] with this [Lifecycle] in a [Lifecycle.State] of at least [Lifecycle.State.RESUMED]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> Lifecycle.withResumed(
+ crossinline block: () -> R
+): R = withStateAtLeastUnchecked(
+ state = Lifecycle.State.RESUMED,
+ block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least [state]
+ * and resume with the result. Throws the [CancellationException] [LifecycleDestroyedException]
+ * if the lifecycle has reached [Lifecycle.State.DESTROYED] by the time of the call or before
+ * [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withStateAtLeast(
+ state: Lifecycle.State,
+ crossinline block: () -> R
+): R = lifecycle.withStateAtLeast(
+ state = state,
+ block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least
+ * [Lifecycle.State.CREATED] and resume with the result.
+ * Throws the [CancellationException] [LifecycleDestroyedException] if the lifecycle has reached
+ * [Lifecycle.State.DESTROYED] by the time of the call or before [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withCreated(
+ crossinline block: () -> R
+): R = lifecycle.withStateAtLeastUnchecked(
+ state = Lifecycle.State.CREATED,
+ block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least
+ * [Lifecycle.State.STARTED] and resume with the result.
+ * Throws the [CancellationException] [LifecycleDestroyedException] if the lifecycle has reached
+ * [Lifecycle.State.DESTROYED] by the time of the call or before [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withStarted(
+ crossinline block: () -> R
+): R = lifecycle.withStateAtLeastUnchecked(
+ state = Lifecycle.State.STARTED,
+ block = block
+)
+
+/**
+ * Run [block] with this [LifecycleOwner]'s [Lifecycle] in a [Lifecycle.State] of at least
+ * [Lifecycle.State.RESUMED] and resume with the result.
+ * Throws the [CancellationException] [LifecycleDestroyedException] if the lifecycle has reached
+ * [Lifecycle.State.DESTROYED] by the time of the call or before [block] is able to run.
+ */
+suspend inline fun <R> LifecycleOwner.withResumed(
+ crossinline block: () -> R
+): R = lifecycle.withStateAtLeastUnchecked(
+ state = Lifecycle.State.RESUMED,
+ block = block
+)
+
+/**
+ * The inlined check for whether dispatch is necessary to perform [Lifecycle.withStateAtLeast]
+ * operations that does not bounds-check [state]. Used internally when we know the target state
+ * is already in bounds. Runs [block] inline without allocating if possible.
+ */
+@PublishedApi
+internal suspend inline fun <R> Lifecycle.withStateAtLeastUnchecked(
+ state: Lifecycle.State,
+ crossinline block: () -> R
+): R {
+ // Fast path: if our lifecycle dispatcher doesn't require dispatch we can check
+ // the current lifecycle state and decide if we can run synchronously
+ val lifecycleDispatcher = Dispatchers.Main.immediate
+ val dispatchNeeded = lifecycleDispatcher.isDispatchNeeded(coroutineContext)
+ if (!dispatchNeeded) {
+ if (currentState == Lifecycle.State.DESTROYED) throw LifecycleDestroyedException()
+ if (currentState >= state) return block()
+ }
+
+ return suspendWithStateAtLeastUnchecked(state, dispatchNeeded, lifecycleDispatcher) {
+ block()
+ }
+}
+
+/**
+ * The "slow" code path for [Lifecycle.withStateAtLeast] operations that requires allocating
+ * and suspending, factored into a non-inlined function to avoid inflating code size at call sites
+ * or exposing too many implementation details as inlined code.
+ */
+@PublishedApi
+internal suspend fun <R> Lifecycle.suspendWithStateAtLeastUnchecked(
+ state: Lifecycle.State,
+ dispatchNeeded: Boolean,
+ lifecycleDispatcher: CoroutineDispatcher,
+ block: () -> R
+): R = suspendCancellableCoroutine { co ->
+ val observer = object : LifecycleEventObserver {
+ override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
+ if (event == Lifecycle.Event.upTo(state)) {
+ removeObserver(this)
+ co.resumeWith(runCatching(block))
+ } else if (event == Lifecycle.Event.ON_DESTROY) {
+ removeObserver(this)
+ co.resumeWithException(LifecycleDestroyedException())
+ }
+ }
+ }
+
+ if (dispatchNeeded) {
+ lifecycleDispatcher.dispatch(
+ EmptyCoroutineContext,
+ Runnable { addObserver(observer) }
+ )
+ } else addObserver(observer)
+
+ co.invokeOnCancellation {
+ if (lifecycleDispatcher.isDispatchNeeded(EmptyCoroutineContext)) {
+ lifecycleDispatcher.dispatch(
+ EmptyCoroutineContext,
+ Runnable { removeObserver(observer) }
+ )
+ } else removeObserver(observer)
+ }
+}
diff --git a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java
index 43a92e5..6a29743 100644
--- a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java
+++ b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.java
@@ -16,17 +16,8 @@
package androidx.lifecycle;
-import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
-import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
-import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
-import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
-import static androidx.lifecycle.Lifecycle.Event.ON_START;
-import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
-import static androidx.lifecycle.Lifecycle.State.CREATED;
import static androidx.lifecycle.Lifecycle.State.DESTROYED;
import static androidx.lifecycle.Lifecycle.State.INITIALIZED;
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-import static androidx.lifecycle.Lifecycle.State.STARTED;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
@@ -127,8 +118,7 @@
* @param event The event that was received
*/
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
- State next = getStateAfter(event);
- moveToState(next);
+ moveToState(event.getTargetState());
}
private void moveToState(State next) {
@@ -185,7 +175,11 @@
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
- statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
+ final Event event = Event.upFrom(statefulObserver.mState);
+ if (event == null) {
+ throw new IllegalStateException("no event up from " + statefulObserver.mState);
+ }
+ statefulObserver.dispatchEvent(lifecycleOwner, event);
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
@@ -239,55 +233,6 @@
return mState;
}
- static State getStateAfter(Event event) {
- switch (event) {
- case ON_CREATE:
- case ON_STOP:
- return CREATED;
- case ON_START:
- case ON_PAUSE:
- return STARTED;
- case ON_RESUME:
- return RESUMED;
- case ON_DESTROY:
- return DESTROYED;
- case ON_ANY:
- break;
- }
- throw new IllegalArgumentException("Unexpected event value " + event);
- }
-
- private static Event downEvent(State state) {
- switch (state) {
- case INITIALIZED:
- throw new IllegalArgumentException();
- case CREATED:
- return ON_DESTROY;
- case STARTED:
- return ON_STOP;
- case RESUMED:
- return ON_PAUSE;
- case DESTROYED:
- throw new IllegalArgumentException();
- }
- throw new IllegalArgumentException("Unexpected state value " + state);
- }
-
- private static Event upEvent(State state) {
- switch (state) {
- case INITIALIZED:
- case DESTROYED:
- return ON_CREATE;
- case CREATED:
- return ON_START;
- case STARTED:
- return ON_RESUME;
- case RESUMED:
- throw new IllegalArgumentException();
- }
- throw new IllegalArgumentException("Unexpected state value " + state);
- }
-
private void forwardPass(LifecycleOwner lifecycleOwner) {
Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
mObserverMap.iteratorWithAdditions();
@@ -297,7 +242,11 @@
while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
pushParentState(observer.mState);
- observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
+ final Event event = Event.upFrom(observer.mState);
+ if (event == null) {
+ throw new IllegalStateException("no event up from " + observer.mState);
+ }
+ observer.dispatchEvent(lifecycleOwner, event);
popParentState();
}
}
@@ -311,8 +260,11 @@
ObserverWithState observer = entry.getValue();
while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
- Event event = downEvent(observer.mState);
- pushParentState(getStateAfter(event));
+ Event event = Event.downFrom(observer.mState);
+ if (event == null) {
+ throw new IllegalStateException("no event down from " + observer.mState);
+ }
+ pushParentState(event.getTargetState());
observer.dispatchEvent(lifecycleOwner, event);
popParentState();
}
@@ -356,7 +308,7 @@
}
void dispatchEvent(LifecycleOwner owner, Event event) {
- State newState = getStateAfter(event);
+ State newState = event.getTargetState();
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
diff --git a/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java b/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java
index 414fb28..6f1f317 100644
--- a/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java
+++ b/lifecycle/lifecycle-runtime/src/test/java/androidx/lifecycle/LifecycleRegistryTest.java
@@ -280,10 +280,6 @@
final TestObserver observer2 = mock(TestObserver.class);
mRegistry.addObserver(observer2);
verify(observer2, never()).onCreate();
- reset(observer1);
- dispatchEvent(ON_CREATE);
- verify(observer1).onCreate();
- verify(observer2).onCreate();
}
@Test
@@ -605,7 +601,7 @@
}
private void dispatchEvent(Lifecycle.Event event) {
- when(mLifecycle.getCurrentState()).thenReturn(LifecycleRegistry.getStateAfter(event));
+ when(mLifecycle.getCurrentState()).thenReturn(event.getTargetState());
mRegistry.handleLifecycleEvent(event);
}
diff --git a/media2/common/api/api_lint.ignore b/media2/common/api/api_lint.ignore
index d2bb9aa..d3d06d5 100644
--- a/media2/common/api/api_lint.ignore
+++ b/media2/common/api/api_lint.ignore
@@ -13,9 +13,5 @@
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.media2.common.MediaMetadata.Builder.putText(String,CharSequence)
-GenericException: androidx.media2.common.SessionPlayer#close():
- Methods must not throw generic exceptions (`java.lang.Exception`)
-
-
IntentName: androidx.media2.common.MediaMetadata#METADATA_KEY_EXTRAS:
Intent extra constant name must be EXTRA_FOO: METADATA_KEY_EXTRAS
diff --git a/media2/player/api/api_lint.ignore b/media2/player/api/api_lint.ignore
index f6d216c..bc67ff2 100644
--- a/media2/player/api/api_lint.ignore
+++ b/media2/player/api/api_lint.ignore
@@ -7,9 +7,5 @@
Must avoid boxed primitives (`java.lang.Float`)
-GenericException: androidx.media2.player.MediaPlayer#close():
- Methods must not throw generic exceptions (`java.lang.Exception`)
-
-
MissingNullability: androidx.media2.player.TimedMetaData#getMetaData():
Missing nullability on method `getMetaData` return
diff --git a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
similarity index 94%
rename from media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
rename to media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
index 1ab31ca..5a31569 100644
--- a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
+++ b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
@@ -68,8 +68,8 @@
* Tests whether {@link MediaBrowserCompat} works well with {@link MediaLibraryService}.
*/
@LargeTest
-public class MediaBrowserCompatTestWithMediaLibraryService extends
- MediaBrowserCompatTestWithMediaSessionService {
+public class MediaBrowserCompatWithMediaLibraryServiceTest extends
+ MediaBrowserCompatWithMediaSessionServiceTest {
@Override
public void setUp() throws Exception {
super.setUp();
@@ -86,7 +86,7 @@
}
@Test
- public void testGetRoot() throws InterruptedException {
+ public void getRoot() throws InterruptedException {
// The MockMediaLibraryService gives MediaBrowserConstants.ROOT_ID as root ID, and
// MediaBrowserConstants.ROOT_EXTRAS as extras.
sHandler.postAndSync(new Runnable() {
@@ -105,7 +105,7 @@
}
@Test
- public void testGetItem() throws InterruptedException {
+ public void getItem() throws InterruptedException {
final String mediaId = MEDIA_ID_GET_ITEM;
connectAndWait();
@@ -122,7 +122,7 @@
}
@Test
- public void testGetItem_nullResult() throws InterruptedException {
+ public void getItem_nullResult() throws InterruptedException {
final String mediaId = "random_media_id";
connectAndWait();
@@ -143,7 +143,7 @@
}
@Test
- public void testGetChildren() throws InterruptedException {
+ public void getChildren() throws InterruptedException {
final String testParentId = PARENT_ID;
connectAndWait();
@@ -173,7 +173,7 @@
}
@Test
- public void testGetChildren_withLongList() throws InterruptedException {
+ public void getChildren_withLongList() throws InterruptedException {
final String testParentId = PARENT_ID_LONG_LIST;
connectAndWait();
@@ -203,7 +203,7 @@
}
@Test
- public void testGetChildren_withPagination() throws InterruptedException {
+ public void getChildren_withPagination() throws InterruptedException {
final String testParentId = PARENT_ID;
final int page = 4;
final int pageSize = 10;
@@ -246,7 +246,7 @@
}
@Test
- public void testGetChildren_emptyResult() throws InterruptedException {
+ public void getChildren_emptyResult() throws InterruptedException {
final String testParentId = PARENT_ID_NO_CHILDREN;
connectAndWait();
@@ -264,7 +264,7 @@
}
@Test
- public void testGetChildren_nullResult() throws InterruptedException {
+ public void getChildren_nullResult() throws InterruptedException {
final String testParentId = PARENT_ID_ERROR;
connectAndWait();
@@ -286,7 +286,7 @@
}
@Test
- public void testSearch() throws InterruptedException {
+ public void search() throws InterruptedException {
final String testQuery = SEARCH_QUERY;
final int page = 4;
final int pageSize = 10;
@@ -325,7 +325,7 @@
}
@Test
- public void testSearch_withLongList() throws InterruptedException {
+ public void search_withLongList() throws InterruptedException {
final String testQuery = SEARCH_QUERY_LONG_LIST;
final int page = 0;
final int pageSize = Integer.MAX_VALUE;
@@ -355,7 +355,7 @@
}
@Test
- public void testSearch_emptyResult() throws InterruptedException {
+ public void search_emptyResult() throws InterruptedException {
final String testQuery = SEARCH_QUERY_EMPTY_RESULT;
final Bundle testExtras = new Bundle();
testExtras.putString(testQuery, testQuery);
@@ -377,7 +377,7 @@
}
@Test
- public void testSearch_error() throws InterruptedException {
+ public void search_error() throws InterruptedException {
final String testQuery = SEARCH_QUERY_ERROR;
final Bundle testExtras = new Bundle();
testExtras.putString(testQuery, testQuery);
@@ -403,7 +403,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribe() throws InterruptedException {
+ public void subscribe() throws InterruptedException {
// final String testParentId = "testSubscribeId";
// final List<MediaItem> testList = TestUtils.createMediaItems(3);
//
@@ -448,7 +448,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribe_withExtras() throws InterruptedException {
+ public void subscribe_withExtras() throws InterruptedException {
// final String testParentId = "testSubscribe_withExtras";
// final Bundle testExtras = new Bundle();
// testExtras.putString(testParentId, testParentId);
@@ -499,7 +499,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribe_withPagination() throws InterruptedException {
+ public void subscribe_withPagination() throws InterruptedException {
// final String testParentId = "testSubscribe_pagination_ID";
// final List<MediaItem> testList = TestUtils.createMediaItems(3);
// final int testPage = 2;
@@ -565,7 +565,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribeAndUnsubscribe() throws InterruptedException {
+ public void subscribeAndUnsubscribe() throws InterruptedException {
// final String testParentId = "testUnsubscribe";
// final Bundle testExtras = new Bundle();
// testExtras.putString(testParentId, testParentId);
@@ -605,7 +605,7 @@
@Ignore("TODO: Split this test to here and MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testNotifyChildrenChanged() throws InterruptedException {
+ public void notifyChildrenChanged() throws InterruptedException {
// final String testSubscribedParentId = "testNotifyChildrenChanged";
// final String testUnsubscribedParentId = "testNotifyChildrenChanged22";
// final Bundle testExtras = new Bundle();
@@ -658,7 +658,7 @@
// TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
@Test
- public void testCustomAction() throws InterruptedException {
+ public void customAction() throws InterruptedException {
final Bundle testArgs = new Bundle();
testArgs.putString("args_key", "args_value");
@@ -678,7 +678,7 @@
// TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
@Test
- public void testCustomAction_rejected() throws InterruptedException {
+ public void customAction_rejected() throws InterruptedException {
// This action will not be allowed by the library session.
final String testAction = "random_custom_action";
diff --git a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
similarity index 93%
rename from media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
rename to media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
index 41c0cea..07fd59f 100644
--- a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
+++ b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
@@ -41,7 +41,7 @@
* Tests whether {@link MediaBrowserCompat} works well with {@link MediaSessionService}.
*/
@LargeTest
-public class MediaBrowserCompatTestWithMediaSessionService extends MediaSessionTestBase {
+public class MediaBrowserCompatWithMediaSessionServiceTest extends MediaSessionTestBase {
MediaBrowserCompat mBrowserCompat;
TestConnectionCallback mConnectionCallback;
@@ -79,21 +79,21 @@
}
@Test
- public void testConnect() throws InterruptedException {
+ public void connect() throws InterruptedException {
connectAndWait();
assertNotEquals(0, mConnectionCallback.mFailedLatch.getCount());
}
@Ignore
@Test
- public void testConnect_rejected() throws InterruptedException {
+ public void connect_rejected() throws InterruptedException {
// TODO: Connect the browser to the session service whose onConnect() returns null.
assertTrue(mConnectionCallback.mFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertNotEquals(0, mConnectionCallback.mConnectedLatch.getCount());
}
@Test
- public void testGetSessionToken() throws Exception {
+ public void getSessionToken() throws Exception {
connectAndWait();
MediaControllerCompat controller = new MediaControllerCompat(mContext,
mBrowserCompat.getSessionToken());
diff --git a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
similarity index 95%
rename from media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
rename to media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
index e5d1fd7..178411f 100644
--- a/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
+++ b/media2/session/version-compat-tests/current/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
@@ -58,7 +58,7 @@
*/
@RunWith(AndroidJUnit4.class)
@LargeTest
-public class MediaControllerCompatCallbackTestWithMediaSession extends MediaSessionTestBase {
+public class MediaControllerCompatCallbackWithMediaSessionTest extends MediaSessionTestBase {
private static final String TAG = "MCCCallbackTestWithMS2";
private static final long TIMEOUT_MS = 1000L;
@@ -82,7 +82,7 @@
}
@Test
- public void testRepeatModeChange() throws Exception {
+ public void repeatModeChange() throws Exception {
final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -97,7 +97,7 @@
}
@Test
- public void testShuffleModeChange() throws Exception {
+ public void shuffleModeChange() throws Exception {
final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -112,7 +112,7 @@
}
@Test
- public void testClose() throws Exception {
+ public void close() throws Exception {
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
controllerCallback.reset(1);
mControllerCompat.registerCallback(controllerCallback, sHandler);
@@ -123,7 +123,7 @@
}
@Test
- public void testUpdatePlayer() throws Exception {
+ public void updatePlayer() throws Exception {
final int testState = SessionPlayer.PLAYER_STATE_PLAYING;
final int testBufferingPosition = 1500;
final float testSpeed = 1.5f;
@@ -176,7 +176,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeChangedToRemote() throws Exception {
+ public void updatePlayer_playbackTypeChangedToRemote() throws Exception {
final int controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
final int maxVolume = 25;
final int currentVolume = 10;
@@ -212,7 +212,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeChangedToLocal() throws Exception {
+ public void updatePlayer_playbackTypeChangedToLocal() throws Exception {
Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder()
.setVolumeControlType(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE)
.setMaxVolume(10)
@@ -258,7 +258,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeNotChanged_local() throws Exception {
+ public void updatePlayer_playbackTypeNotChanged_local() throws Exception {
final int legacyStream = AudioManager.STREAM_RING;
final AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
.setLegacyStreamType(legacyStream).build();
@@ -296,7 +296,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeNotChanged_remote() throws Exception {
+ public void updatePlayer_playbackTypeNotChanged_remote() throws Exception {
Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder()
.setVolumeControlType(VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE)
.setMaxVolume(10)
@@ -347,7 +347,7 @@
}
@Test
- public void testPlayerStateChange() throws Exception {
+ public void playerStateChange() throws Exception {
final int targetState = SessionPlayer.PLAYER_STATE_PLAYING;
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -363,7 +363,7 @@
}
@Test
- public void testPlaybackSpeedChange() throws Exception {
+ public void playbackSpeedChange() throws Exception {
final float speed = 1.5f;
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -378,7 +378,7 @@
}
@Test
- public void testBufferingStateChange() throws Exception {
+ public void bufferingStateChange() throws Exception {
final List<MediaItem> testPlaylist = MediaTestUtils.createFileMediaItems(3);
final int testItemIndex = 0;
final int testBufferingState = SessionPlayer.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
@@ -398,7 +398,7 @@
}
@Test
- public void testSeekComplete() throws Exception {
+ public void seekComplete() throws Exception {
final long testSeekPosition = 1300;
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
@@ -414,7 +414,7 @@
}
@Test
- public void testCurrentMediaItemChange() throws Exception {
+ public void currentMediaItemChange() throws Exception {
String displayTitle = "displayTitle";
MediaMetadata metadata = new MediaMetadata.Builder()
.putText(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, displayTitle).build();
@@ -441,7 +441,7 @@
}
@Test
- public void testPlaylistAndPlaylistMetadataChange() throws Exception {
+ public void playlistAndPlaylistMetadataChange() throws Exception {
final List<MediaItem> playlist = MediaTestUtils.createFileMediaItems(5);
final String playlistTitle = "playlistTitle";
MediaMetadata playlistMetadata = new MediaMetadata.Builder()
@@ -469,7 +469,7 @@
}
@Test
- public void testPlaylistAndPlaylistMetadataChange_longList() throws Exception {
+ public void playlistAndPlaylistMetadataChange_longList() throws Exception {
final String playlistTitle = "playlistTitle";
MediaMetadata playlistMetadata = new MediaMetadata.Builder()
.putText(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, playlistTitle).build();
@@ -505,7 +505,7 @@
}
@Test
- public void testPlaylistMetadataChange() throws Exception {
+ public void playlistMetadataChange() throws Exception {
final String playlistTitle = "playlistTitle";
MediaMetadata playlistMetadata = new MediaMetadata.Builder()
.putText(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, playlistTitle).build();
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
similarity index 93%
rename from media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
rename to media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
index e52d782..9e39b4b 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
@@ -53,7 +53,7 @@
* Tests {@link MediaBrowser} with {@link MediaBrowserServiceCompat}.
*/
@LargeTest
-public class MediaBrowserServiceCompatCallbackTestWithMediaBrowser extends MediaSessionTestBase {
+public class MediaBrowserServiceCompatCallbackWithMediaBrowserTest extends MediaSessionTestBase {
private SessionToken mToken;
@Before
@@ -71,7 +71,7 @@
}
@Test
- public void testOnGetRootCalledByGetLibraryRoot() throws InterruptedException {
+ public void onGetRootCalledByGetLibraryRoot() throws InterruptedException {
final String testMediaId = "testOnGetRootCalledByGetLibraryRoot";
final Bundle testExtras = new Bundle();
testExtras.putString(testMediaId, testMediaId);
@@ -100,7 +100,7 @@
}
@Test
- public void testOnLoadItemCalledByGetItem() throws InterruptedException {
+ public void onLoadItemCalledByGetItem() throws InterruptedException {
final String testMediaId = "test_media_item";
final MediaItem testItem = createMediaItem(testMediaId);
final CountDownLatch latch = new CountDownLatch(1);
@@ -119,7 +119,7 @@
}
@Test
- public void testOnLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
+ public void onLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
final String testParentId = "test_media_parent";
final int testPage = 2;
final int testPageSize = 4;
@@ -140,7 +140,7 @@
}
@Test
- public void testOnLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
+ public void onLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
final String testParentId = "test_media_parent";
final int testPage = 2;
final int testPageSize = 4;
@@ -169,7 +169,7 @@
}
@Test
- public void testOnLoadChildrenCalledBySubscribe() throws InterruptedException {
+ public void onLoadChildrenCalledBySubscribe() throws InterruptedException {
final String testParentId = "testOnLoadChildrenCalledBySubscribe";
final LibraryParams testParams = MediaTestUtils.createLibraryParams();
final CountDownLatch subscribeLatch = new CountDownLatch(1);
@@ -189,7 +189,7 @@
}
@Test
- public void testOnSearchCalledBySearch() throws InterruptedException {
+ public void onSearchCalledBySearch() throws InterruptedException {
final String testQuery = "search_query";
final int testPage = 2;
final int testPageSize = 4;
@@ -214,7 +214,7 @@
}
@Test
- public void testOnSearchCalledByGetSearchResult() throws InterruptedException {
+ public void onSearchCalledByGetSearchResult() throws InterruptedException {
final String testQuery = "search_query";
final int testPage = 2;
final int testPageSize = 4;
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
similarity index 94%
rename from media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
rename to media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
index 4f1b9f7..40db1de 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
@@ -81,7 +81,7 @@
*/
@RunWith(AndroidJUnit4.class)
@LargeTest
-public class MediaSessionCallbackTestWithMediaControllerCompat extends MediaSessionTestBase {
+public class MediaSessionCallbackWithMediaControllerCompatTest extends MediaSessionTestBase {
private static final String TAG = "MediaSessionCallbackTestWithMediaControllerCompat";
private static final long VOLUME_CHANGE_TIMEOUT_MS = 5000L;
@@ -153,7 +153,7 @@
}
@Test
- public void testDisconnectedAfterTimeout() throws InterruptedException {
+ public void disconnectedAfterTimeout() throws InterruptedException {
CountDownLatch disconnectedLatch = new CountDownLatch(1);
try (MediaSession session = new MediaSession.Builder(mContext, mPlayer)
.setId("testDisconnectedAfterTimeout")
@@ -186,7 +186,7 @@
}
@Test
- public void testConnectedCallbackAfterDisconnectedByTimeout() throws InterruptedException {
+ public void connectedCallbackAfterDisconnectedByTimeout() throws InterruptedException {
CountDownLatch connectedLatch = new CountDownLatch(1);
CountDownLatch disconnectedLatch = new CountDownLatch(1);
try (MediaSession session = new MediaSession.Builder(mContext, mPlayer)
@@ -227,7 +227,7 @@
}
@Test
- public void testPlay() {
+ public void play() {
mController.getTransportControls().play();
try {
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -238,7 +238,7 @@
}
@Test
- public void testPause() {
+ public void pause() {
mController.getTransportControls().pause();
try {
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -249,7 +249,7 @@
}
@Test
- public void testStop() {
+ public void stop() {
// MediaControllerCompat#stop() will call MediaSession#pause() and MediaSession#seekTo(0).
// Therefore, the latch's initial count is 2.
MockPlayer player = new MockPlayer(2);
@@ -268,7 +268,7 @@
}
@Test
- public void testPrepare() {
+ public void prepare() {
mController.getTransportControls().prepare();
try {
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -279,7 +279,7 @@
}
@Test
- public void testSeekTo() {
+ public void seekTo() {
final long seekPosition = 12125L;
mController.getTransportControls().seekTo(seekPosition);
try {
@@ -292,7 +292,7 @@
}
@Test
- public void testSetPlaybackSpeed() {
+ public void setPlaybackSpeed() {
final float testSpeed = 2.0f;
mController.getTransportControls().setPlaybackSpeed(testSpeed);
try {
@@ -305,7 +305,7 @@
}
@Test
- public void testAddQueueItem() throws InterruptedException {
+ public void addQueueItem() throws InterruptedException {
final int playlistSize = 10;
List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -327,7 +327,7 @@
}
@Test
- public void testAddQueueItemWithIndex() throws InterruptedException {
+ public void addQueueItemWithIndex() throws InterruptedException {
final int playlistSize = 10;
List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -351,7 +351,7 @@
}
@Test
- public void testRemoveQueueItem() throws InterruptedException {
+ public void removeQueueItem() throws InterruptedException {
final int playlistSize = 10;
List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -374,21 +374,21 @@
}
@Test
- public void testSkipToPrevious() throws InterruptedException {
+ public void skipToPrevious() throws InterruptedException {
mController.getTransportControls().skipToPrevious();
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertTrue(mPlayer.mSkipToPreviousItemCalled);
}
@Test
- public void testSkipToNext() throws InterruptedException {
+ public void skipToNext() throws InterruptedException {
mController.getTransportControls().skipToNext();
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertTrue(mPlayer.mSkipToNextItemCalled);
}
@Test
- public void testSkipToQueueItem() throws InterruptedException {
+ public void skipToQueueItem() throws InterruptedException {
final int playlistSize = 10;
List<MediaItem> playlist = MediaTestUtils.createPlaylist(playlistSize);
@@ -408,7 +408,7 @@
}
@Test
- public void testSetShuffleMode() throws InterruptedException {
+ public void setShuffleMode() throws InterruptedException {
final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
mController.getTransportControls().setShuffleMode(testShuffleMode);
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -418,7 +418,7 @@
}
@Test
- public void testSetRepeatMode() throws InterruptedException {
+ public void setRepeatMode() throws InterruptedException {
final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
mController.getTransportControls().setRepeatMode(testRepeatMode);
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -428,7 +428,7 @@
}
@Test
- public void testSetVolumeTo() throws Exception {
+ public void setVolumeTo() throws Exception {
final int maxVolume = 100;
final int currentVolume = 23;
final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -445,7 +445,7 @@
}
@Test
- public void testAdjustVolume() throws Exception {
+ public void adjustVolume() throws Exception {
final int maxVolume = 100;
final int currentVolume = 23;
final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -462,7 +462,7 @@
}
@Test
- public void testSetVolumeWithLocalVolume() throws Exception {
+ public void setVolumeWithLocalVolume() throws Exception {
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
return;
@@ -504,7 +504,7 @@
}
@Test
- public void testAdjustVolumeWithLocalVolume() throws Exception {
+ public void adjustVolumeWithLocalVolume() throws Exception {
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
return;
@@ -547,7 +547,7 @@
}
@Test
- public void testSendCommand() throws InterruptedException {
+ public void sendCommand() throws InterruptedException {
// TODO(jaewan): Need to revisit with the permission.
final String testCommand = "test_command";
final Bundle testArgs = new Bundle();
@@ -586,7 +586,7 @@
}
@Test
- public void testControllerCallback_sessionRejects() throws Exception {
+ public void controllerCallback_sessionRejects() throws Exception {
final SessionCallback sessionCallback = new SessionCallback() {
@Override
public SessionCommandGroup onConnect(@NonNull MediaSession session,
@@ -611,7 +611,7 @@
}
@Test
- public void testFastForward() throws InterruptedException {
+ public void fastForward() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
final SessionCallback callback = new SessionCallback() {
@Override
@@ -633,7 +633,7 @@
}
@Test
- public void testRewind() throws InterruptedException {
+ public void rewind() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
final SessionCallback callback = new SessionCallback() {
@Override
@@ -654,7 +654,7 @@
}
@Test
- public void testPrepareFromMediaUri() throws InterruptedException {
+ public void prepareFromMediaUri() throws InterruptedException {
final Uri mediaId = Uri.parse("foo://bar");
final Bundle bundle = new Bundle();
bundle.putString("key", "value");
@@ -683,7 +683,7 @@
}
@Test
- public void testPlayFromMediaUri() throws InterruptedException {
+ public void playFromMediaUri() throws InterruptedException {
final Uri request = Uri.parse("foo://bar");
final Bundle bundle = new Bundle();
bundle.putString("key", "value");
@@ -712,7 +712,7 @@
}
@Test
- public void testPrepareFromMediaId() throws InterruptedException {
+ public void prepareFromMediaId() throws InterruptedException {
final String request = "media_id";
final Bundle bundle = new Bundle();
bundle.putString("key", "value");
@@ -742,7 +742,7 @@
}
@Test
- public void testPlayFromMediaId() throws InterruptedException {
+ public void playFromMediaId() throws InterruptedException {
final String mediaId = "media_id";
final Bundle bundle = new Bundle();
bundle.putString("key", "value");
@@ -772,7 +772,7 @@
}
@Test
- public void testPrepareFromSearch() throws InterruptedException {
+ public void prepareFromSearch() throws InterruptedException {
final String query = "test_query";
final Bundle bundle = new Bundle();
bundle.putString("key", "value");
@@ -802,7 +802,7 @@
}
@Test
- public void testPlayFromSearch() throws InterruptedException {
+ public void playFromSearch() throws InterruptedException {
final String query = "test_query";
final Bundle bundle = new Bundle();
bundle.putString("key", "value");
@@ -832,7 +832,7 @@
}
@Test
- public void testSetRating() throws InterruptedException {
+ public void setRating() throws InterruptedException {
final int ratingType = RatingCompat.RATING_5_STARS;
final float ratingValue = 3.5f;
final RatingCompat rating = RatingCompat.newStarRating(ratingType, ratingValue);
@@ -864,7 +864,7 @@
}
@Test
- public void testOnCommandCallback() throws InterruptedException {
+ public void onCommandCallback() throws InterruptedException {
final ArrayList<SessionCommand> commands = new ArrayList<>();
final CountDownLatch latchForPause = new CountDownLatch(1);
final SessionCallback callback = new SessionCallback() {
@@ -917,7 +917,7 @@
*/
@Test
@LargeTest
- public void testDeadlock() throws InterruptedException {
+ public void deadlock() throws InterruptedException {
sHandler.postAndSync(new Runnable() {
@Override
public void run() {
@@ -995,7 +995,7 @@
@Test
@LargeTest
- public void testControllerAfterSessionIsGone() throws InterruptedException {
+ public void controllerAfterSessionIsGone() throws InterruptedException {
mSession.close();
testSessionCallbackIsNotCalled();
diff --git a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
similarity index 95%
rename from media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
rename to media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
index c075943..3c3f3292 100644
--- a/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
+++ b/media2/session/version-compat-tests/current/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
@@ -70,7 +70,7 @@
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class MediaSessionCompatCallbackTestWithMediaController extends MediaSessionTestBase {
+public class MediaSessionCompatCallbackWithMediaControllerTest extends MediaSessionTestBase {
private static final String TAG = "MediaControllerTest";
// The maximum time to wait for an operation.
@@ -123,7 +123,7 @@
}
@Test
- public void testPlay() throws Exception {
+ public void play() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -133,7 +133,7 @@
}
@Test
- public void testPause() throws Exception {
+ public void pause() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -143,7 +143,7 @@
}
@Test
- public void testPrepare() throws Exception {
+ public void prepare() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -153,7 +153,7 @@
}
@Test
- public void testSeekTo() throws Exception {
+ public void seekTo() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -165,7 +165,7 @@
}
@Test
- public void testSetPlaybackSpeed() throws Exception {
+ public void setPlaybackSpeed() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -177,7 +177,7 @@
}
@Test
- public void testAddPlaylistItem() throws Exception {
+ public void addPlaylistItem() throws Exception {
final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
final String testMediaId = "testAddPlaylistItem";
@@ -197,7 +197,7 @@
}
@Test
- public void testRemovePlaylistItem() throws Exception {
+ public void removePlaylistItem() throws Exception {
final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -216,7 +216,7 @@
}
@Test
- public void testReplacePlaylistItem() throws Exception {
+ public void replacePlaylistItem() throws Exception {
final int testReplaceIndex = 1;
// replace = remove + add
final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
@@ -242,7 +242,7 @@
}
@Test
- public void testSkipToPreviousItem() throws Exception {
+ public void skipToPreviousItem() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -252,7 +252,7 @@
}
@Test
- public void testSkipToNextItem() throws Exception {
+ public void skipToNextItem() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -262,7 +262,7 @@
}
@Test
- public void testSkipToPlaylistItem() throws Exception {
+ public void skipToPlaylistItem() throws Exception {
final int testSkipToIndex = 1;
final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -279,7 +279,7 @@
}
@Test
- public void testSetShuffleMode() throws Exception {
+ public void setShuffleMode() throws Exception {
final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
mSession.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_NONE);
@@ -293,7 +293,7 @@
}
@Test
- public void testSetRepeatMode() throws Exception {
+ public void setRepeatMode() throws Exception {
final int testRepeatMode = SessionPlayer.REPEAT_MODE_ALL;
mSession.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_NONE);
@@ -307,7 +307,7 @@
}
@Test
- public void testSetVolumeTo() throws Exception {
+ public void setVolumeTo() throws Exception {
final int maxVolume = 100;
final int currentVolume = 23;
final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -324,7 +324,7 @@
}
@Test
- public void testAdjustVolume() throws Exception {
+ public void adjustVolume() throws Exception {
final int maxVolume = 100;
final int currentVolume = 23;
final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
@@ -341,7 +341,7 @@
}
@Test
- public void testSetVolumeWithLocalVolume() throws Exception {
+ public void setVolumeWithLocalVolume() throws Exception {
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
return;
@@ -378,7 +378,7 @@
}
@Test
- public void testAdjustVolumeWithLocalVolume() throws Exception {
+ public void adjustVolumeWithLocalVolume() throws Exception {
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
return;
@@ -417,7 +417,7 @@
}
@Test
- public void testSendCustomCommand() throws Exception {
+ public void sendCustomCommand() throws Exception {
final String command = "test_custom_command";
final Bundle testArgs = new Bundle();
testArgs.putString("args", "test_args");
@@ -433,7 +433,7 @@
}
@Test
- public void testFastForward() throws Exception {
+ public void fastForward() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -443,7 +443,7 @@
}
@Test
- public void testRewind() throws Exception {
+ public void rewind() throws Exception {
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -453,7 +453,7 @@
}
@Test
- public void testSetRating() throws Exception {
+ public void setRating() throws Exception {
final float ratingValue = 3.5f;
final Rating rating2 = new StarRating(5, ratingValue);
final String mediaId = "media_id";
diff --git a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
similarity index 94%
rename from media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
rename to media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
index 17a9dfd..1331de22 100644
--- a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaLibraryService.java
+++ b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaLibraryServiceTest.java
@@ -67,8 +67,8 @@
* Tests whether {@link MediaBrowserCompat} works well with {@link MediaLibraryService}.
*/
@LargeTest
-public class MediaBrowserCompatTestWithMediaLibraryService extends
- MediaBrowserCompatTestWithMediaSessionService {
+public class MediaBrowserCompatWithMediaLibraryServiceTest extends
+ MediaBrowserCompatWithMediaSessionServiceTest {
@Override
public void setUp() throws Exception {
super.setUp();
@@ -85,7 +85,7 @@
}
@Test
- public void testGetRoot() throws InterruptedException {
+ public void getRoot() throws InterruptedException {
prepareLooper();
// The MockMediaLibraryService gives MediaBrowserConstants.ROOT_ID as root ID, and
// MediaBrowserConstants.ROOT_EXTRAS as extras.
@@ -105,7 +105,7 @@
}
@Test
- public void testGetItem() throws InterruptedException {
+ public void getItem() throws InterruptedException {
prepareLooper();
final String mediaId = MEDIA_ID_GET_ITEM;
@@ -123,7 +123,7 @@
}
@Test
- public void testGetItem_nullResult() throws InterruptedException {
+ public void getItem_nullResult() throws InterruptedException {
prepareLooper();
final String mediaId = "random_media_id";
@@ -145,7 +145,7 @@
}
@Test
- public void testGetChildren() throws InterruptedException {
+ public void getChildren() throws InterruptedException {
prepareLooper();
final String testParentId = PARENT_ID;
@@ -174,7 +174,7 @@
}
@Test
- public void testGetChildren_withLongList() throws InterruptedException {
+ public void getChildren_withLongList() throws InterruptedException {
prepareLooper();
final String testParentId = PARENT_ID_LONG_LIST;
@@ -203,7 +203,7 @@
}
@Test
- public void testGetChildren_withPagination() throws InterruptedException {
+ public void getChildren_withPagination() throws InterruptedException {
prepareLooper();
final String testParentId = PARENT_ID;
final int page = 4;
@@ -246,7 +246,7 @@
}
@Test
- public void testGetChildren_emptyResult() throws InterruptedException {
+ public void getChildren_emptyResult() throws InterruptedException {
prepareLooper();
final String testParentId = PARENT_ID_NO_CHILDREN;
@@ -264,7 +264,7 @@
}
@Test
- public void testGetChildren_nullResult() throws InterruptedException {
+ public void getChildren_nullResult() throws InterruptedException {
prepareLooper();
final String testParentId = PARENT_ID_ERROR;
@@ -287,7 +287,7 @@
}
@Test
- public void testSearch() throws InterruptedException {
+ public void search() throws InterruptedException {
prepareLooper();
final String testQuery = SEARCH_QUERY;
final int page = 4;
@@ -326,7 +326,7 @@
}
@Test
- public void testSearch_withLongList() throws InterruptedException {
+ public void search_withLongList() throws InterruptedException {
prepareLooper();
final String testQuery = SEARCH_QUERY_LONG_LIST;
final int page = 0;
@@ -356,7 +356,7 @@
}
@Test
- public void testSearch_emptyResult() throws InterruptedException {
+ public void search_emptyResult() throws InterruptedException {
prepareLooper();
final String testQuery = SEARCH_QUERY_EMPTY_RESULT;
final Bundle testExtras = new Bundle();
@@ -378,7 +378,7 @@
}
@Test
- public void testSearch_error() throws InterruptedException {
+ public void search_error() throws InterruptedException {
prepareLooper();
final String testQuery = SEARCH_QUERY_ERROR;
final Bundle testExtras = new Bundle();
@@ -404,7 +404,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribe() throws InterruptedException {
+ public void subscribe() throws InterruptedException {
// prepareLooper();
// final String testParentId = "testSubscribeId";
// final List<MediaItem> testList = TestUtils.createMediaItems(3);
@@ -450,7 +450,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribe_withExtras() throws InterruptedException {
+ public void subscribe_withExtras() throws InterruptedException {
// prepareLooper();
// final String testParentId = "testSubscribe_withExtras";
// final Bundle testExtras = new Bundle();
@@ -502,7 +502,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribe_withPagination() throws InterruptedException {
+ public void subscribe_withPagination() throws InterruptedException {
// prepareLooper();
// final String testParentId = "testSubscribe_pagination_ID";
// final List<MediaItem> testList = TestUtils.createMediaItems(3);
@@ -569,7 +569,7 @@
@Ignore("TODO: Move this test to MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testSubscribeAndUnsubscribe() throws InterruptedException {
+ public void subscribeAndUnsubscribe() throws InterruptedException {
// prepareLooper();
// final String testParentId = "testUnsubscribe";
// final Bundle testExtras = new Bundle();
@@ -610,7 +610,7 @@
@Ignore("TODO: Split this test to here and MediaLibrarySessionLegacyCallbackTest.")
@Test
- public void testNotifyChildrenChanged() throws InterruptedException {
+ public void notifyChildrenChanged() throws InterruptedException {
// prepareLooper();
// final String testSubscribedParentId = "testNotifyChildrenChanged";
// final String testUnsubscribedParentId = "testNotifyChildrenChanged22";
@@ -664,7 +664,7 @@
// TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
@Test
- public void testCustomAction() throws InterruptedException {
+ public void customAction() throws InterruptedException {
prepareLooper();
final Bundle testArgs = new Bundle();
testArgs.putString("args_key", "args_value");
@@ -685,7 +685,7 @@
// TODO: Add test for onCustomCommand() in MediaLibrarySessionLegacyCallbackTest.
@Test
- public void testCustomAction_rejected() throws InterruptedException {
+ public void customAction_rejected() throws InterruptedException {
prepareLooper();
// This action will not be allowed by the library session.
final String testAction = "random_custom_action";
diff --git a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
similarity index 93%
rename from media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
rename to media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
index 7c04129..94d3f10 100644
--- a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatTestWithMediaSessionService.java
+++ b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaBrowserCompatWithMediaSessionServiceTest.java
@@ -41,7 +41,7 @@
* Tests whether {@link MediaBrowserCompat} works well with {@link MediaSessionService}.
*/
@LargeTest
-public class MediaBrowserCompatTestWithMediaSessionService extends MediaSessionTestBase {
+public class MediaBrowserCompatWithMediaSessionServiceTest extends MediaSessionTestBase {
MediaBrowserCompat mBrowserCompat;
TestConnectionCallback mConnectionCallback;
@@ -79,7 +79,7 @@
}
@Test
- public void testConnect() throws InterruptedException {
+ public void connect() throws InterruptedException {
prepareLooper();
connectAndWait();
assertNotEquals(0, mConnectionCallback.mFailedLatch.getCount());
@@ -87,7 +87,7 @@
@Ignore
@Test
- public void testConnect_rejected() throws InterruptedException {
+ public void connect_rejected() throws InterruptedException {
prepareLooper();
// TODO: Connect the browser to the session service whose onConnect() returns null.
assertTrue(mConnectionCallback.mFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -95,7 +95,7 @@
}
@Test
- public void testGetSessionToken() throws Exception {
+ public void getSessionToken() throws Exception {
prepareLooper();
connectAndWait();
MediaControllerCompat controller = new MediaControllerCompat(mContext,
diff --git a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
similarity index 95%
rename from media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
rename to media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
index 0532b3c..407d7ca 100644
--- a/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackTestWithMediaSession.java
+++ b/media2/session/version-compat-tests/previous/client/src/androidTest/java/androidx/media2/test/client/tests/MediaControllerCompatCallbackWithMediaSessionTest.java
@@ -57,7 +57,7 @@
*/
@RunWith(AndroidJUnit4.class)
@LargeTest
-public class MediaControllerCompatCallbackTestWithMediaSession extends MediaSessionTestBase {
+public class MediaControllerCompatCallbackWithMediaSessionTest extends MediaSessionTestBase {
private static final String TAG = "MCCCallbackTestWithMS2";
private static final long TIMEOUT_MS = 1000L;
@@ -81,7 +81,7 @@
}
@Test
- public void testRepeatModeChange() throws Exception {
+ public void repeatModeChange() throws Exception {
prepareLooper();
final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
@@ -97,7 +97,7 @@
}
@Test
- public void testShuffleModeChange() throws Exception {
+ public void shuffleModeChange() throws Exception {
prepareLooper();
final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
@@ -113,7 +113,7 @@
}
@Test
- public void testClose() throws Exception {
+ public void close() throws Exception {
prepareLooper();
final MediaControllerCallback controllerCallback = new MediaControllerCallback();
controllerCallback.reset(1);
@@ -125,7 +125,7 @@
}
@Test
- public void testUpdatePlayer() throws Exception {
+ public void updatePlayer() throws Exception {
prepareLooper();
final int testState = SessionPlayer.PLAYER_STATE_PLAYING;
final int testBufferingPosition = 1500;
@@ -175,7 +175,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeChangedToRemote() throws Exception {
+ public void updatePlayer_playbackTypeChangedToRemote() throws Exception {
prepareLooper();
final int controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
final int maxVolume = 25;
@@ -209,7 +209,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeChangedToLocal() throws Exception {
+ public void updatePlayer_playbackTypeChangedToLocal() throws Exception {
prepareLooper();
Bundle prevPlayerConfig = RemoteMediaSession.createMockPlayerConnectorConfig(
VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 10 /* maxVolume */,
@@ -253,7 +253,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeNotChanged_local() throws Exception {
+ public void updatePlayer_playbackTypeNotChanged_local() throws Exception {
final int legacyStream = AudioManager.STREAM_RING;
final AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
.setLegacyStreamType(legacyStream).build();
@@ -290,7 +290,7 @@
}
@Test
- public void testUpdatePlayer_playbackTypeNotChanged_remote() throws Exception {
+ public void updatePlayer_playbackTypeNotChanged_remote() throws Exception {
prepareLooper();
Bundle prevPlayerConfig = RemoteMediaSession.createMockPlayerConnectorConfig(
VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 10 /* maxVolume */,
@@ -337,7 +337,7 @@
}
@Test
- public void testPlayerStateChange() throws Exception {
+ public void playerStateChange() throws Exception {
prepareLooper();
final int targetState = SessionPlayer.PLAYER_STATE_PLAYING;
@@ -354,7 +354,7 @@
}
@Test
- public void testPlaybackSpeedChange() throws Exception {
+ public void playbackSpeedChange() throws Exception {
prepareLooper();
final float speed = 1.5f;
@@ -370,7 +370,7 @@
}
@Test
- public void testBufferingStateChange() throws Exception {
+ public void bufferingStateChange() throws Exception {
prepareLooper();
final List<MediaItem> testPlaylist = MediaTestUtils.createFileMediaItems(3);
final int testItemIndex = 0;
@@ -391,7 +391,7 @@
}
@Test
- public void testSeekComplete() throws Exception {
+ public void seekComplete() throws Exception {
prepareLooper();
final long testSeekPosition = 1300;
@@ -408,7 +408,7 @@
}
@Test
- public void testCurrentMediaItemChange() throws Exception {
+ public void currentMediaItemChange() throws Exception {
prepareLooper();
String displayTitle = "displayTitle";
@@ -437,7 +437,7 @@
}
@Test
- public void testPlaylistAndPlaylistMetadataChange() throws Exception {
+ public void playlistAndPlaylistMetadataChange() throws Exception {
prepareLooper();
final List<MediaItem> playlist = MediaTestUtils.createFileMediaItems(5);
final String playlistTitle = "playlistTitle";
@@ -466,7 +466,7 @@
}
@Test
- public void testPlaylistAndPlaylistMetadataChange_longList() throws Exception {
+ public void playlistAndPlaylistMetadataChange_longList() throws Exception {
prepareLooper();
final String playlistTitle = "playlistTitle";
MediaMetadata playlistMetadata = new MediaMetadata.Builder()
@@ -503,7 +503,7 @@
}
@Test
- public void testPlaylistMetadataChange() throws Exception {
+ public void playlistMetadataChange() throws Exception {
prepareLooper();
final String playlistTitle = "playlistTitle";
MediaMetadata playlistMetadata = new MediaMetadata.Builder()
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
similarity index 93%
rename from media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
rename to media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
index c94f144..f0bd07f 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackTestWithMediaBrowser.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaBrowserServiceCompatCallbackWithMediaBrowserTest.java
@@ -53,7 +53,7 @@
* Tests {@link MediaBrowser} with {@link MediaBrowserServiceCompat}.
*/
@LargeTest
-public class MediaBrowserServiceCompatCallbackTestWithMediaBrowser extends MediaSessionTestBase {
+public class MediaBrowserServiceCompatCallbackWithMediaBrowserTest extends MediaSessionTestBase {
private SessionToken mToken;
@Before
@@ -71,7 +71,7 @@
}
@Test
- public void testOnGetRootCalledByGetLibraryRoot() throws InterruptedException {
+ public void onGetRootCalledByGetLibraryRoot() throws InterruptedException {
prepareLooper();
final String testMediaId = "testOnGetRootCalledByGetLibraryRoot";
final Bundle testExtras = new Bundle();
@@ -101,7 +101,7 @@
}
@Test
- public void testOnLoadItemCalledByGetItem() throws InterruptedException {
+ public void onLoadItemCalledByGetItem() throws InterruptedException {
prepareLooper();
final String testMediaId = "test_media_item";
final MediaItem testItem = createMediaItem(testMediaId);
@@ -121,7 +121,7 @@
}
@Test
- public void testOnLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
+ public void onLoadChildrenWithoutOptionsCalledByGetChildren() throws InterruptedException {
prepareLooper();
final String testParentId = "test_media_parent";
final int testPage = 2;
@@ -143,7 +143,7 @@
}
@Test
- public void testOnLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
+ public void onLoadChildrenWithOptionsCalledByGetChildren() throws InterruptedException {
prepareLooper();
final String testParentId = "test_media_parent";
final int testPage = 2;
@@ -173,7 +173,7 @@
}
@Test
- public void testOnLoadChildrenCalledBySubscribe() throws InterruptedException {
+ public void onLoadChildrenCalledBySubscribe() throws InterruptedException {
prepareLooper();
final String testParentId = "testOnLoadChildrenCalledBySubscribe";
final LibraryParams testParams = MediaTestUtils.createLibraryParams();
@@ -194,7 +194,7 @@
}
@Test
- public void testOnSearchCalledBySearch() throws InterruptedException {
+ public void onSearchCalledBySearch() throws InterruptedException {
prepareLooper();
final String testQuery = "search_query";
final int testPage = 2;
@@ -220,7 +220,7 @@
}
@Test
- public void testOnSearchCalledByGetSearchResult() throws InterruptedException {
+ public void onSearchCalledByGetSearchResult() throws InterruptedException {
prepareLooper();
final String testQuery = "search_query";
final int testPage = 2;
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
similarity index 94%
rename from media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
rename to media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
index 63c46aa..443d768 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackTestWithMediaControllerCompat.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCallbackWithMediaControllerCompatTest.java
@@ -80,7 +80,7 @@
*/
@RunWith(AndroidJUnit4.class)
@LargeTest
-public class MediaSessionCallbackTestWithMediaControllerCompat extends MediaSessionTestBase {
+public class MediaSessionCallbackWithMediaControllerCompatTest extends MediaSessionTestBase {
private static final String TAG = "MediaSessionCallbackTestWithMediaControllerCompat";
private static final long VOLUME_CHANGE_TIMEOUT_MS = 5000L;
@@ -145,7 +145,7 @@
}
@Test
- public void testPlay() {
+ public void play() {
prepareLooper();
mController.getTransportControls().play();
try {
@@ -157,7 +157,7 @@
}
@Test
- public void testPause() {
+ public void pause() {
prepareLooper();
mController.getTransportControls().pause();
try {
@@ -169,7 +169,7 @@
}
@Test
- public void testStop() {
+ public void stop() {
prepareLooper();
// MediaControllerCompat#stop() will call MediaSession#pause() and MediaSession#seekTo(0).
@@ -190,7 +190,7 @@
}
@Test
- public void testPrepare() {
+ public void prepare() {
prepareLooper();
mController.getTransportControls().prepare();
try {
@@ -202,7 +202,7 @@
}
@Test
- public void testSeekTo() {
+ public void seekTo() {
prepareLooper();
final long seekPosition = 12125L;
mController.getTransportControls().seekTo(seekPosition);
@@ -216,7 +216,7 @@
}
@Test
- public void testAddQueueItem() throws InterruptedException {
+ public void addQueueItem() throws InterruptedException {
prepareLooper();
final int playlistSize = 10;
@@ -239,7 +239,7 @@
}
@Test
- public void testAddQueueItemWithIndex() throws InterruptedException {
+ public void addQueueItemWithIndex() throws InterruptedException {
prepareLooper();
final int playlistSize = 10;
@@ -264,7 +264,7 @@
}
@Test
- public void testRemoveQueueItem() throws InterruptedException {
+ public void removeQueueItem() throws InterruptedException {
prepareLooper();
final int playlistSize = 10;
@@ -288,7 +288,7 @@
}
@Test
- public void testSkipToPrevious() throws InterruptedException {
+ public void skipToPrevious() throws InterruptedException {
prepareLooper();
mController.getTransportControls().skipToPrevious();
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -296,7 +296,7 @@
}
@Test
- public void testSkipToNext() throws InterruptedException {
+ public void skipToNext() throws InterruptedException {
prepareLooper();
mController.getTransportControls().skipToNext();
assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -304,7 +304,7 @@
}
@Test
- public void testSkipToQueueItem() throws InterruptedException {
+ public void skipToQueueItem() throws InterruptedException {
prepareLooper();
final int playlistSize = 10;
@@ -325,7 +325,7 @@
}
@Test
- public void testSetShuffleMode() throws InterruptedException {
+ public void setShuffleMode() throws InterruptedException {
prepareLooper();
final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
mController.getTransportControls().setShuffleMode(testShuffleMode);
@@ -336,7 +336,7 @@
}
@Test
- public void testSetRepeatMode() throws InterruptedException {
+ public void setRepeatMode() throws InterruptedException {
prepareLooper();
final int testRepeatMode = SessionPlayer.REPEAT_MODE_GROUP;
mController.getTransportControls().setRepeatMode(testRepeatMode);
@@ -347,7 +347,7 @@
}
@Test
- public void testSetVolumeTo() throws Exception {
+ public void setVolumeTo() throws Exception {
prepareLooper();
final int maxVolume = 100;
final int currentVolume = 23;
@@ -365,7 +365,7 @@
}
@Test
- public void testAdjustVolume() throws Exception {
+ public void adjustVolume() throws Exception {
prepareLooper();
final int maxVolume = 100;
final int currentVolume = 23;
@@ -383,7 +383,7 @@
}
@Test
- public void testSetVolumeWithLocalVolume() throws Exception {
+ public void setVolumeWithLocalVolume() throws Exception {
prepareLooper();
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
@@ -426,7 +426,7 @@
}
@Test
- public void testAdjustVolumeWithLocalVolume() throws Exception {
+ public void adjustVolumeWithLocalVolume() throws Exception {
prepareLooper();
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
@@ -470,7 +470,7 @@
}
@Test
- public void testSendCommand() throws InterruptedException {
+ public void sendCommand() throws InterruptedException {
prepareLooper();
// TODO(jaewan): Need to revisit with the permission.
final String testCommand = "test_command";
@@ -508,7 +508,7 @@
}
@Test
- public void testControllerCallback_sessionRejects() throws Exception {
+ public void controllerCallback_sessionRejects() throws Exception {
prepareLooper();
final SessionCallback sessionCallback = new SessionCallback() {
@Override
@@ -534,7 +534,7 @@
}
@Test
- public void testFastForward() throws InterruptedException {
+ public void fastForward() throws InterruptedException {
prepareLooper();
final CountDownLatch latch = new CountDownLatch(1);
final SessionCallback callback = new SessionCallback() {
@@ -556,7 +556,7 @@
}
@Test
- public void testRewind() throws InterruptedException {
+ public void rewind() throws InterruptedException {
prepareLooper();
final CountDownLatch latch = new CountDownLatch(1);
final SessionCallback callback = new SessionCallback() {
@@ -578,7 +578,7 @@
}
@Test
- public void testPlayFromSearch() throws InterruptedException {
+ public void playFromSearch() throws InterruptedException {
prepareLooper();
final String request = "random query";
final Bundle bundle = new Bundle();
@@ -607,7 +607,7 @@
}
@Test
- public void testPlayFromUri() throws InterruptedException {
+ public void playFromUri() throws InterruptedException {
prepareLooper();
final Uri request = Uri.parse("foo://boo");
final Bundle bundle = new Bundle();
@@ -635,7 +635,7 @@
}
@Test
- public void testPlayFromMediaId() throws InterruptedException {
+ public void playFromMediaId() throws InterruptedException {
prepareLooper();
final String request = "media_id";
final Bundle bundle = new Bundle();
@@ -663,7 +663,7 @@
}
@Test
- public void testPrepareFromSearch() throws InterruptedException {
+ public void prepareFromSearch() throws InterruptedException {
prepareLooper();
final String request = "random query";
final Bundle bundle = new Bundle();
@@ -691,7 +691,7 @@
}
@Test
- public void testPrepareFromUri() throws InterruptedException {
+ public void prepareFromUri() throws InterruptedException {
prepareLooper();
final Uri request = Uri.parse("foo://boo");
final Bundle bundle = new Bundle();
@@ -719,7 +719,7 @@
}
@Test
- public void testPrepareFromMediaId() throws InterruptedException {
+ public void prepareFromMediaId() throws InterruptedException {
prepareLooper();
final String request = "media_id";
final Bundle bundle = new Bundle();
@@ -747,7 +747,7 @@
}
@Test
- public void testSetRating() throws InterruptedException {
+ public void setRating() throws InterruptedException {
prepareLooper();
final int ratingType = RatingCompat.RATING_5_STARS;
final float ratingValue = 3.5f;
@@ -779,7 +779,7 @@
}
@Test
- public void testOnCommandCallback() throws InterruptedException {
+ public void onCommandCallback() throws InterruptedException {
prepareLooper();
final ArrayList<SessionCommand> commands = new ArrayList<>();
final CountDownLatch latchForPause = new CountDownLatch(1);
@@ -833,7 +833,7 @@
*/
@Test
@LargeTest
- public void testDeadlock() throws InterruptedException {
+ public void deadlock() throws InterruptedException {
prepareLooper();
sHandler.postAndSync(new Runnable() {
@Override
@@ -912,7 +912,7 @@
@Test
@LargeTest
- public void testControllerAfterSessionIsGone() throws InterruptedException {
+ public void controllerAfterSessionIsGone() throws InterruptedException {
prepareLooper();
mSession.close();
testSessionCallbackIsNotCalled();
diff --git a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
similarity index 95%
rename from media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
rename to media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
index b45271c..34c30d96 100644
--- a/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackTestWithMediaController.java
+++ b/media2/session/version-compat-tests/previous/service/src/androidTest/java/androidx/media2/test/service/tests/MediaSessionCompatCallbackWithMediaControllerTest.java
@@ -70,7 +70,7 @@
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class MediaSessionCompatCallbackTestWithMediaController extends MediaSessionTestBase {
+public class MediaSessionCompatCallbackWithMediaControllerTest extends MediaSessionTestBase {
private static final String TAG = "MediaControllerTest";
// The maximum time to wait for an operation.
@@ -127,7 +127,7 @@
}
@Test
- public void testPlay() throws Exception {
+ public void play() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -138,7 +138,7 @@
}
@Test
- public void testPause() throws Exception {
+ public void pause() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -149,7 +149,7 @@
}
@Test
- public void testPrepare() throws Exception {
+ public void prepare() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -160,7 +160,7 @@
}
@Test
- public void testSeekTo() throws Exception {
+ public void seekTo() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -173,7 +173,7 @@
}
@Test
- public void testAddPlaylistItem() throws Exception {
+ public void addPlaylistItem() throws Exception {
prepareLooper();
final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -194,7 +194,7 @@
}
@Test
- public void testRemovePlaylistItem() throws Exception {
+ public void removePlaylistItem() throws Exception {
prepareLooper();
final List<MediaItem> testList = MediaTestUtils.createPlaylist(2);
final List<QueueItem> testQueue = MediaUtils.convertToQueueItemList(testList);
@@ -214,7 +214,7 @@
}
@Test
- public void testReplacePlaylistItem() throws Exception {
+ public void replacePlaylistItem() throws Exception {
prepareLooper();
final int testReplaceIndex = 1;
// replace = remove + add
@@ -241,7 +241,7 @@
}
@Test
- public void testSkipToPreviousItem() throws Exception {
+ public void skipToPreviousItem() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -252,7 +252,7 @@
}
@Test
- public void testSkipToNextItem() throws Exception {
+ public void skipToNextItem() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -263,7 +263,7 @@
}
@Test
- public void testSkipToPlaylistItem() throws Exception {
+ public void skipToPlaylistItem() throws Exception {
prepareLooper();
final int testSkipToIndex = 1;
@@ -282,7 +282,7 @@
}
@Test
- public void testSetShuffleMode() throws Exception {
+ public void setShuffleMode() throws Exception {
prepareLooper();
final int testShuffleMode = SessionPlayer.SHUFFLE_MODE_GROUP;
@@ -297,7 +297,7 @@
}
@Test
- public void testSetRepeatMode() throws Exception {
+ public void setRepeatMode() throws Exception {
prepareLooper();
final int testRepeatMode = SessionPlayer.REPEAT_MODE_ALL;
@@ -312,7 +312,7 @@
}
@Test
- public void testSetVolumeTo() throws Exception {
+ public void setVolumeTo() throws Exception {
prepareLooper();
final int maxVolume = 100;
final int currentVolume = 23;
@@ -330,7 +330,7 @@
}
@Test
- public void testAdjustVolume() throws Exception {
+ public void adjustVolume() throws Exception {
prepareLooper();
final int maxVolume = 100;
final int currentVolume = 23;
@@ -348,7 +348,7 @@
}
@Test
- public void testSetVolumeWithLocalVolume() throws Exception {
+ public void setVolumeWithLocalVolume() throws Exception {
prepareLooper();
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
@@ -386,7 +386,7 @@
}
@Test
- public void testAdjustVolumeWithLocalVolume() throws Exception {
+ public void adjustVolumeWithLocalVolume() throws Exception {
prepareLooper();
if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
// This test is not eligible for this device.
@@ -426,7 +426,7 @@
}
@Test
- public void testSendCustomCommand() throws Exception {
+ public void sendCustomCommand() throws Exception {
prepareLooper();
final String command = "test_custom_command";
final Bundle testArgs = new Bundle();
@@ -443,7 +443,7 @@
}
@Test
- public void testFastForward() throws Exception {
+ public void fastForward() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -454,7 +454,7 @@
}
@Test
- public void testRewind() throws Exception {
+ public void rewind() throws Exception {
prepareLooper();
RemoteMediaController controller = createControllerAndWaitConnection();
mSessionCallback.reset(1);
@@ -465,7 +465,7 @@
}
@Test
- public void testSetRating() throws Exception {
+ public void setRating() throws Exception {
prepareLooper();
final float ratingValue = 3.5f;
final Rating rating2 = new StarRating(5, ratingValue);
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
index 751cdfbe..8629127 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2Provider.java
@@ -176,6 +176,16 @@
MediaRouter2Utils.KEY_MESSENGER);
}
+ @Nullable
+ static String getSessionIdForRouteController(@Nullable RouteController controller) {
+ if (!(controller instanceof DynamicMediaRoute2Controller)) {
+ return null;
+ }
+ MediaRouter2.RoutingController routingController =
+ ((DynamicMediaRoute2Controller) controller).mRoutingController;
+ return (routingController == null) ? null : routingController.getId();
+ }
+
private class RouteCallback extends MediaRouter2.RouteCallback {
RouteCallback() {}
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java
index af7b763..cac56397 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRoute2ProviderServiceAdapter.java
@@ -54,6 +54,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -279,6 +280,7 @@
(descriptor == null) ? Collections.emptyList() : descriptor.getRoutes();
// Handle duplicated IDs
notifyRoutes(routeDescriptors.stream().map(MediaRouter2Utils::toFwkMediaRoute2Info)
+ .filter(Objects::nonNull)
.collect(Collectors.toMap(r -> r.getId(), r -> r, (a, b) -> b)).values());
}
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
index 4eb5d6d..bccb6de 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -3181,6 +3181,7 @@
return -1;
}
+ @SuppressLint("NewApi")
private void updatePlaybackInfoFromSelectedRoute() {
if (mSelectedRoute != null) {
mPlaybackInfo.volume = mSelectedRoute.getVolume();
@@ -3188,6 +3189,12 @@
mPlaybackInfo.volumeHandling = mSelectedRoute.getVolumeHandling();
mPlaybackInfo.playbackStream = mSelectedRoute.getPlaybackStream();
mPlaybackInfo.playbackType = mSelectedRoute.getPlaybackType();
+ if (mTransferEnabled && mSelectedRoute.getProviderInstance() == mMr2Provider) {
+ mPlaybackInfo.volumeControlId = MediaRoute2Provider
+ .getSessionIdForRouteController(mSelectedRouteController);
+ } else {
+ mPlaybackInfo.volumeControlId = null;
+ }
final int count = mRemoteControlClients.size();
for (int i = 0; i < count; i++) {
@@ -3207,7 +3214,7 @@
controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
}
mMediaSession.configureVolume(controlType, mPlaybackInfo.volumeMax,
- mPlaybackInfo.volume);
+ mPlaybackInfo.volume, mPlaybackInfo.volumeControlId);
}
}
} else {
@@ -3300,7 +3307,7 @@
}
public void configureVolume(@VolumeProviderCompat.ControlType int controlType,
- int max, int current) {
+ int max, int current, @Nullable String volumeControlId) {
if (mMsCompat != null) {
if (mVpCompat != null && controlType == mControlType && max == mMaxVolume) {
// If we haven't changed control type or max just set the
@@ -3308,7 +3315,8 @@
mVpCompat.setCurrentVolume(current);
} else {
// Otherwise create a new provider and update
- mVpCompat = new VolumeProviderCompat(controlType, max, current) {
+ mVpCompat = new VolumeProviderCompat(controlType, max, current,
+ volumeControlId) {
@Override
public void onSetVolumeTo(final int volume) {
mCallbackHandler.post(new Runnable() {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java
index f006a82..93f3879 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/RemoteControlClientCompat.java
@@ -19,6 +19,7 @@
import android.media.AudioManager;
import android.os.Build;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import java.lang.ref.WeakReference;
@@ -77,6 +78,8 @@
public int volumeHandling = MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED;
public int playbackStream = AudioManager.STREAM_MUSIC;
public int playbackType = MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
+ @Nullable
+ public String volumeControlId;
}
/**
diff --git a/navigation/benchmark/src/androidTest/AndroidManifest.xml b/navigation/benchmark/src/androidTest/AndroidManifest.xml
index 03cb61f..358a851 100644
--- a/navigation/benchmark/src/androidTest/AndroidManifest.xml
+++ b/navigation/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
index e812316..4c95e72 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavBackStackEntry.java
@@ -205,7 +205,10 @@
return mSavedStateHandle;
}
- // Copied from LifecycleRegistry.getStateAfter()
+ /**
+ * Copied from LifecycleRegistry.getStateAfter()
+ * TODO: update to Event.getTargetState() when navigation's lifecycle-core dependency is updated
+ */
@NonNull
private static Lifecycle.State getStateAfter(@NonNull Lifecycle.Event event) {
switch (event) {
diff --git a/paging/common/api/3.0.0-alpha03.txt b/paging/common/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..dd27c13
--- /dev/null
+++ b/paging/common/api/3.0.0-alpha03.txt
@@ -0,0 +1,457 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ public final class CachedPagingDataKt {
+ method @CheckResult public static <T> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>> cachedIn(kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ }
+
+ public final class CancelableChannelFlowKt {
+ }
+
+ public final class CombinedLoadStates {
+ ctor public CombinedLoadStates(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+ method public androidx.paging.LoadStates component1();
+ method public androidx.paging.LoadStates? component2();
+ method public androidx.paging.CombinedLoadStates copy(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+ method public androidx.paging.LoadState getAppend();
+ method public androidx.paging.LoadStates? getMediator();
+ method public androidx.paging.LoadState getPrepend();
+ method public androidx.paging.LoadState getRefresh();
+ method public androidx.paging.LoadStates getSource();
+ property public final androidx.paging.LoadState append;
+ property public final androidx.paging.LoadState prepend;
+ property public final androidx.paging.LoadState refresh;
+ }
+
+ public abstract class DataSource<Key, Value> {
+ method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+ method @AnyThread public final void addInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ method @AnyThread public void invalidate();
+ method @WorkerThread public boolean isInvalid();
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+ method @AnyThread public final void removeInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ property @WorkerThread public boolean isInvalid;
+ }
+
+ public abstract static class DataSource.Factory<Key, Value> {
+ ctor public DataSource.Factory();
+ method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = Dispatchers.IO);
+ method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory();
+ method public abstract androidx.paging.DataSource<Key,Value> create();
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ public static interface DataSource.InvalidatedCallback {
+ method @AnyThread public void onInvalidated();
+ }
+
+ @kotlin.RequiresOptIn public @interface ExperimentalPagingApi {
+ }
+
+ @Deprecated public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+ ctor @Deprecated public ItemKeyedDataSource();
+ method @Deprecated public abstract Key getKey(Value item);
+ method @Deprecated public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+ method @Deprecated public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+ method @Deprecated public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value> callback);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ @Deprecated public abstract static class ItemKeyedDataSource.LoadCallback<Value> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data);
+ }
+
+ @Deprecated public abstract static class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback<Value> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount);
+ }
+
+ @Deprecated public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadInitialParams(Key? requestedInitialKey, int requestedLoadSize, boolean placeholdersEnabled);
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final Key? requestedInitialKey;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public static class ItemKeyedDataSource.LoadParams<Key> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+ field @Deprecated public final Key key;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ public abstract sealed class LoadState {
+ method public final boolean getEndOfPaginationReached();
+ }
+
+ public static final class LoadState.Error extends androidx.paging.LoadState {
+ ctor public LoadState.Error(Throwable error);
+ method public Throwable getError();
+ }
+
+ public static final class LoadState.Loading extends androidx.paging.LoadState {
+ field public static final androidx.paging.LoadState.Loading INSTANCE;
+ }
+
+ public static final class LoadState.NotLoading extends androidx.paging.LoadState {
+ ctor public LoadState.NotLoading(boolean endOfPaginationReached);
+ }
+
+ public final class LoadStates {
+ ctor public LoadStates(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+ method public androidx.paging.LoadState component1();
+ method public androidx.paging.LoadState component2();
+ method public androidx.paging.LoadState component3();
+ method public androidx.paging.LoadStates copy(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+ method public androidx.paging.LoadState getAppend();
+ method public androidx.paging.LoadState getPrepend();
+ method public androidx.paging.LoadState getRefresh();
+ }
+
+ public enum LoadType {
+ method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.LoadType[] values();
+ enum_constant public static final androidx.paging.LoadType APPEND;
+ enum_constant public static final androidx.paging.LoadType PREPEND;
+ enum_constant public static final androidx.paging.LoadType REFRESH;
+ }
+
+ public final class PageEventKt {
+ }
+
+ @Deprecated public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+ ctor @Deprecated public PageKeyedDataSource();
+ method @Deprecated public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+ method @Deprecated public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+ method @Deprecated public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key,Value> callback);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ @Deprecated public abstract static class PageKeyedDataSource.LoadCallback<Key, Value> {
+ ctor @Deprecated public PageKeyedDataSource.LoadCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? adjacentPageKey);
+ }
+
+ @Deprecated public abstract static class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+ ctor @Deprecated public PageKeyedDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount, Key? previousPageKey, Key? nextPageKey);
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? previousPageKey, Key? nextPageKey);
+ }
+
+ @Deprecated public static class PageKeyedDataSource.LoadInitialParams<Key> {
+ ctor @Deprecated public PageKeyedDataSource.LoadInitialParams(int requestedLoadSize, boolean placeholdersEnabled);
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public static class PageKeyedDataSource.LoadParams<Key> {
+ ctor @Deprecated public PageKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+ field @Deprecated public final Key key;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public abstract class PagedList<T> extends java.util.AbstractList<T> {
+ method @Deprecated public final void addWeakCallback(java.util.List<? extends T>? previousSnapshot, androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void addWeakCallback(androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void addWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public abstract void detach();
+ method @Deprecated public T? get(int index);
+ method @Deprecated public final androidx.paging.PagedList.Config getConfig();
+ method @Deprecated public final androidx.paging.DataSource<?,T> getDataSource();
+ method @Deprecated public abstract Object? getLastKey();
+ method @Deprecated public final int getLoadedCount();
+ method @Deprecated public final int getPositionOffset();
+ method @Deprecated public int getSize();
+ method @Deprecated public abstract boolean isDetached();
+ method @Deprecated public boolean isImmutable();
+ method @Deprecated public final void loadAround(int index);
+ method @Deprecated public final void removeWeakCallback(androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void removeWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void retry();
+ method @Deprecated public final java.util.List<T> snapshot();
+ property @Deprecated public final androidx.paging.DataSource<?,T> dataSource;
+ property public abstract boolean isDetached;
+ property public boolean isImmutable;
+ property public abstract Object? lastKey;
+ property public final int loadedCount;
+ property public final int positionOffset;
+ property public int size;
+ }
+
+ @Deprecated @MainThread public abstract static class PagedList.BoundaryCallback<T> {
+ ctor @Deprecated public PagedList.BoundaryCallback();
+ method @Deprecated public void onItemAtEndLoaded(T itemAtEnd);
+ method @Deprecated public void onItemAtFrontLoaded(T itemAtFront);
+ method @Deprecated public void onZeroItemsLoaded();
+ }
+
+ @Deprecated public static final class PagedList.Builder<Key, Value> {
+ ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, int pageSize);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, int pageSize);
+ method @Deprecated public androidx.paging.PagedList<Value> build();
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchDispatcher(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setInitialKey(Key? initialKey);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyDispatcher(kotlinx.coroutines.CoroutineDispatcher notifyDispatcher);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyExecutor(java.util.concurrent.Executor notifyExecutor);
+ }
+
+ @Deprecated public abstract static class PagedList.Callback {
+ ctor @Deprecated public PagedList.Callback();
+ method @Deprecated public abstract void onChanged(int position, int count);
+ method @Deprecated public abstract void onInserted(int position, int count);
+ method @Deprecated public abstract void onRemoved(int position, int count);
+ }
+
+ @Deprecated public static final class PagedList.Config {
+ field @Deprecated public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+ field @Deprecated public final boolean enablePlaceholders;
+ field @Deprecated public final int initialLoadSizeHint;
+ field @Deprecated public final int maxSize;
+ field @Deprecated public final int pageSize;
+ field @Deprecated public final int prefetchDistance;
+ }
+
+ @Deprecated public static final class PagedList.Config.Builder {
+ ctor @Deprecated public PagedList.Config.Builder();
+ method @Deprecated public androidx.paging.PagedList.Config build();
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean enablePlaceholders);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(@IntRange(from=1) int initialLoadSizeHint);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setMaxSize(@IntRange(from=2) int maxSize);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setPageSize(@IntRange(from=1) int pageSize);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setPrefetchDistance(@IntRange(from=0) int prefetchDistance);
+ }
+
+ public final class PagedListConfigKt {
+ method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * androidx.paging.PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = 2147483647);
+ }
+
+ public final class PagedListKt {
+ method @Deprecated public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
+ }
+
+ public final class Pager<Key, Value> {
+ ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, androidx.paging.RemoteMediator<Key,Value>? remoteMediator, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ ctor public Pager(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ method public kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> getFlow();
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> flow;
+ }
+
+ public final class PagingConfig {
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize, int jumpThreshold);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
+ ctor public PagingConfig(int pageSize);
+ field public static final androidx.paging.PagingConfig.Companion Companion;
+ field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+ field public final boolean enablePlaceholders;
+ field public final int initialLoadSize;
+ field public final int jumpThreshold;
+ field public final int maxSize;
+ field public final int pageSize;
+ field public final int prefetchDistance;
+ }
+
+ public static final class PagingConfig.Companion {
+ }
+
+ public final class PagingData<T> {
+ method public static <T> androidx.paging.PagingData<T> empty();
+ method @CheckResult public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method @CheckResult public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
+ method @CheckResult public androidx.paging.PagingData<T> insertFooterItem(T item);
+ method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
+ method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+ field public static final androidx.paging.PagingData.Companion Companion;
+ }
+
+ public static final class PagingData.Companion {
+ method public <T> androidx.paging.PagingData<T> empty();
+ method @CheckResult public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
+ public final class PagingDataKt {
+ method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
+ public abstract class PagingSource<Key, Value> {
+ ctor public PagingSource();
+ method public final boolean getInvalid();
+ method public boolean getJumpingSupported();
+ method public boolean getKeyReuseSupported();
+ method @androidx.paging.ExperimentalPagingApi public Key? getRefreshKey(androidx.paging.PagingState<Key,Value> state);
+ method public void invalidate();
+ method public abstract suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+ method public final void registerInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ method public final void unregisterInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ property public final boolean invalid;
+ property public boolean jumpingSupported;
+ property public boolean keyReuseSupported;
+ }
+
+ public abstract static sealed class PagingSource.LoadParams<Key> {
+ method public abstract Key? getKey();
+ method public final int getLoadSize();
+ method @Deprecated public final int getPageSize();
+ method public final boolean getPlaceholdersEnabled();
+ property public abstract Key? key;
+ }
+
+ public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled);
+ method public Key getKey();
+ }
+
+ public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled);
+ method public Key getKey();
+ }
+
+ public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled);
+ method public Key? getKey();
+ }
+
+ public abstract static sealed class PagingSource.LoadResult<Key, Value> {
+ }
+
+ public static final class PagingSource.LoadResult.Error<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+ ctor public PagingSource.LoadResult.Error(Throwable throwable);
+ method public Throwable component1();
+ method public androidx.paging.PagingSource.LoadResult.Error<Key,Value> copy(Throwable throwable);
+ method public Throwable getThrowable();
+ }
+
+ public static final class PagingSource.LoadResult.Page<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+ ctor public PagingSource.LoadResult.Page(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, @IntRange(from=null) int itemsBefore, @IntRange(from=null) int itemsAfter);
+ method public java.util.List<Value> component1();
+ method public Key? component2();
+ method public Key? component3();
+ method public int component4();
+ method public int component5();
+ method public androidx.paging.PagingSource.LoadResult.Page<Key,Value> copy(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, int itemsBefore, int itemsAfter);
+ method public java.util.List<Value> getData();
+ method public int getItemsAfter();
+ method public int getItemsBefore();
+ method public Key? getNextKey();
+ method public Key? getPrevKey();
+ field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
+ field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
+ }
+
+ public static final class PagingSource.LoadResult.Page.Companion {
+ }
+
+ public final class PagingSourceKt {
+ }
+
+ public final class PagingState<Key, Value> {
+ method public Value? closestItemToPosition(int anchorPosition);
+ method public androidx.paging.PagingSource.LoadResult.Page<Key,Value>? closestPageToPosition(int anchorPosition);
+ method public Value? firstItemOrNull();
+ method public Integer? getAnchorPosition();
+ method public androidx.paging.PagingConfig getConfig();
+ method public java.util.List<androidx.paging.PagingSource.LoadResult.Page<Key,Value>> getPages();
+ method public boolean isEmpty();
+ method public Value? lastItemOrNull();
+ }
+
+ @Deprecated public abstract class PositionalDataSource<T> extends androidx.paging.DataSource<java.lang.Integer,T> {
+ ctor @Deprecated public PositionalDataSource();
+ method @Deprecated public static final int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams params, int totalCount);
+ method @Deprecated public static final int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams params, int initialLoadPosition, int totalCount);
+ method @Deprecated @WorkerThread public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+ method @Deprecated @WorkerThread public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T,V> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(kotlin.jvm.functions.Function1<? super T,? extends V> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>,java.util.List<V>> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends T>,? extends java.util.List<? extends V>> function);
+ }
+
+ @Deprecated public abstract static class PositionalDataSource.LoadInitialCallback<T> {
+ ctor @Deprecated public PositionalDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position, int totalCount);
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position);
+ }
+
+ @Deprecated public static class PositionalDataSource.LoadInitialParams {
+ ctor @Deprecated public PositionalDataSource.LoadInitialParams(int requestedStartPosition, int requestedLoadSize, int pageSize, boolean placeholdersEnabled);
+ field @Deprecated public final int pageSize;
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final int requestedLoadSize;
+ field @Deprecated public final int requestedStartPosition;
+ }
+
+ @Deprecated public abstract static class PositionalDataSource.LoadRangeCallback<T> {
+ ctor @Deprecated public PositionalDataSource.LoadRangeCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data);
+ }
+
+ @Deprecated public static class PositionalDataSource.LoadRangeParams {
+ ctor @Deprecated public PositionalDataSource.LoadRangeParams(int startPosition, int loadSize);
+ field @Deprecated public final int loadSize;
+ field @Deprecated public final int startPosition;
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class RemoteMediator<Key, Value> {
+ ctor public RemoteMediator();
+ method public suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> $completion);
+ method public abstract suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ }
+
+ public enum RemoteMediator.InitializeAction {
+ method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.RemoteMediator.InitializeAction[] values();
+ enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
+ enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
+ }
+
+ public abstract static sealed class RemoteMediator.MediatorResult {
+ }
+
+ public static final class RemoteMediator.MediatorResult.Error extends androidx.paging.RemoteMediator.MediatorResult {
+ ctor public RemoteMediator.MediatorResult.Error(Throwable throwable);
+ method public Throwable getThrowable();
+ }
+
+ public static final class RemoteMediator.MediatorResult.Success extends androidx.paging.RemoteMediator.MediatorResult {
+ ctor public RemoteMediator.MediatorResult.Success(boolean endOfPaginationReached);
+ method public boolean endOfPaginationReached();
+ }
+
+ public final class SeparatorsKt {
+ }
+
+}
+
+package androidx.paging.multicast {
+
+ public final class ChannelManagerKt {
+ }
+
+}
+
diff --git a/paging/common/api/current.txt b/paging/common/api/current.txt
index 351532f..dd27c13 100644
--- a/paging/common/api/current.txt
+++ b/paging/common/api/current.txt
@@ -100,7 +100,7 @@
}
public static final class LoadState.Loading extends androidx.paging.LoadState {
- field public static final androidx.paging.LoadState.Loading! INSTANCE;
+ field public static final androidx.paging.LoadState.Loading INSTANCE;
}
public static final class LoadState.NotLoading extends androidx.paging.LoadState {
@@ -119,6 +119,8 @@
}
public enum LoadType {
+ method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.LoadType[] values();
enum_constant public static final androidx.paging.LoadType APPEND;
enum_constant public static final androidx.paging.LoadType PREPEND;
enum_constant public static final androidx.paging.LoadType REFRESH;
@@ -260,7 +262,7 @@
ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
ctor public PagingConfig(int pageSize);
- field public static final androidx.paging.PagingConfig.Companion! Companion;
+ field public static final androidx.paging.PagingConfig.Companion Companion;
field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
field public final boolean enablePlaceholders;
field public final int initialLoadSize;
@@ -281,7 +283,7 @@
method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
- field public static final androidx.paging.PagingData.Companion! Companion;
+ field public static final androidx.paging.PagingData.Companion Companion;
}
public static final class PagingData.Companion {
@@ -358,7 +360,7 @@
method public Key? getNextKey();
method public Key? getPrevKey();
field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
- field public static final androidx.paging.PagingSource.LoadResult.Page.Companion! Companion;
+ field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
}
public static final class PagingSource.LoadResult.Page.Companion {
@@ -422,6 +424,8 @@
}
public enum RemoteMediator.InitializeAction {
+ method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.RemoteMediator.InitializeAction[] values();
enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
}
diff --git a/paging/common/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/common/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..0776c3e
--- /dev/null
+++ b/paging/common/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,459 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ public final class CachedPagingDataKt {
+ method @CheckResult public static <T> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>> cachedIn(kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ }
+
+ public final class CancelableChannelFlowKt {
+ }
+
+ public final class CombinedLoadStates {
+ ctor public CombinedLoadStates(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+ method public androidx.paging.LoadStates component1();
+ method public androidx.paging.LoadStates? component2();
+ method public androidx.paging.CombinedLoadStates copy(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public inline void forEach(kotlin.jvm.functions.Function3<? super androidx.paging.LoadType,? super java.lang.Boolean,? super androidx.paging.LoadState,kotlin.Unit> op);
+ method public androidx.paging.LoadState getAppend();
+ method public androidx.paging.LoadStates? getMediator();
+ method public androidx.paging.LoadState getPrepend();
+ method public androidx.paging.LoadState getRefresh();
+ method public androidx.paging.LoadStates getSource();
+ property public final androidx.paging.LoadState append;
+ property public final androidx.paging.LoadState prepend;
+ property public final androidx.paging.LoadState refresh;
+ }
+
+ public abstract class DataSource<Key, Value> {
+ method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+ method @AnyThread public final void addInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ method @AnyThread public void invalidate();
+ method @WorkerThread public boolean isInvalid();
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+ method @AnyThread public final void removeInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ property @WorkerThread public boolean isInvalid;
+ }
+
+ public abstract static class DataSource.Factory<Key, Value> {
+ ctor public DataSource.Factory();
+ method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = Dispatchers.IO);
+ method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory();
+ method public abstract androidx.paging.DataSource<Key,Value> create();
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ public static interface DataSource.InvalidatedCallback {
+ method @AnyThread public void onInvalidated();
+ }
+
+ @kotlin.RequiresOptIn public @interface ExperimentalPagingApi {
+ }
+
+ @Deprecated public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+ ctor @Deprecated public ItemKeyedDataSource();
+ method @Deprecated public abstract Key getKey(Value item);
+ method @Deprecated public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+ method @Deprecated public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+ method @Deprecated public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value> callback);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ @Deprecated public abstract static class ItemKeyedDataSource.LoadCallback<Value> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data);
+ }
+
+ @Deprecated public abstract static class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback<Value> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount);
+ }
+
+ @Deprecated public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadInitialParams(Key? requestedInitialKey, int requestedLoadSize, boolean placeholdersEnabled);
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final Key? requestedInitialKey;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public static class ItemKeyedDataSource.LoadParams<Key> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+ field @Deprecated public final Key key;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ public abstract sealed class LoadState {
+ method public final boolean getEndOfPaginationReached();
+ }
+
+ public static final class LoadState.Error extends androidx.paging.LoadState {
+ ctor public LoadState.Error(Throwable error);
+ method public Throwable getError();
+ }
+
+ public static final class LoadState.Loading extends androidx.paging.LoadState {
+ field public static final androidx.paging.LoadState.Loading INSTANCE;
+ }
+
+ public static final class LoadState.NotLoading extends androidx.paging.LoadState {
+ ctor public LoadState.NotLoading(boolean endOfPaginationReached);
+ }
+
+ public final class LoadStates {
+ ctor public LoadStates(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+ method public androidx.paging.LoadState component1();
+ method public androidx.paging.LoadState component2();
+ method public androidx.paging.LoadState component3();
+ method public androidx.paging.LoadStates copy(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public inline void forEach(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> op);
+ method public androidx.paging.LoadState getAppend();
+ method public androidx.paging.LoadState getPrepend();
+ method public androidx.paging.LoadState getRefresh();
+ }
+
+ public enum LoadType {
+ method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.LoadType[] values();
+ enum_constant public static final androidx.paging.LoadType APPEND;
+ enum_constant public static final androidx.paging.LoadType PREPEND;
+ enum_constant public static final androidx.paging.LoadType REFRESH;
+ }
+
+ public final class PageEventKt {
+ }
+
+ @Deprecated public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+ ctor @Deprecated public PageKeyedDataSource();
+ method @Deprecated public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+ method @Deprecated public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+ method @Deprecated public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key,Value> callback);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ @Deprecated public abstract static class PageKeyedDataSource.LoadCallback<Key, Value> {
+ ctor @Deprecated public PageKeyedDataSource.LoadCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? adjacentPageKey);
+ }
+
+ @Deprecated public abstract static class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+ ctor @Deprecated public PageKeyedDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount, Key? previousPageKey, Key? nextPageKey);
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? previousPageKey, Key? nextPageKey);
+ }
+
+ @Deprecated public static class PageKeyedDataSource.LoadInitialParams<Key> {
+ ctor @Deprecated public PageKeyedDataSource.LoadInitialParams(int requestedLoadSize, boolean placeholdersEnabled);
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public static class PageKeyedDataSource.LoadParams<Key> {
+ ctor @Deprecated public PageKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+ field @Deprecated public final Key key;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public abstract class PagedList<T> extends java.util.AbstractList<T> {
+ method @Deprecated public final void addWeakCallback(java.util.List<? extends T>? previousSnapshot, androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void addWeakCallback(androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void addWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public abstract void detach();
+ method @Deprecated public T? get(int index);
+ method @Deprecated public final androidx.paging.PagedList.Config getConfig();
+ method @Deprecated public final androidx.paging.DataSource<?,T> getDataSource();
+ method @Deprecated public abstract Object? getLastKey();
+ method @Deprecated public final int getLoadedCount();
+ method @Deprecated public final int getPositionOffset();
+ method @Deprecated public int getSize();
+ method @Deprecated public abstract boolean isDetached();
+ method @Deprecated public boolean isImmutable();
+ method @Deprecated public final void loadAround(int index);
+ method @Deprecated public final void removeWeakCallback(androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void removeWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void retry();
+ method @Deprecated public final java.util.List<T> snapshot();
+ property @Deprecated public final androidx.paging.DataSource<?,T> dataSource;
+ property public abstract boolean isDetached;
+ property public boolean isImmutable;
+ property public abstract Object? lastKey;
+ property public final int loadedCount;
+ property public final int positionOffset;
+ property public int size;
+ }
+
+ @Deprecated @MainThread public abstract static class PagedList.BoundaryCallback<T> {
+ ctor @Deprecated public PagedList.BoundaryCallback();
+ method @Deprecated public void onItemAtEndLoaded(T itemAtEnd);
+ method @Deprecated public void onItemAtFrontLoaded(T itemAtFront);
+ method @Deprecated public void onZeroItemsLoaded();
+ }
+
+ @Deprecated public static final class PagedList.Builder<Key, Value> {
+ ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, int pageSize);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, int pageSize);
+ method @Deprecated public androidx.paging.PagedList<Value> build();
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchDispatcher(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setInitialKey(Key? initialKey);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyDispatcher(kotlinx.coroutines.CoroutineDispatcher notifyDispatcher);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyExecutor(java.util.concurrent.Executor notifyExecutor);
+ }
+
+ @Deprecated public abstract static class PagedList.Callback {
+ ctor @Deprecated public PagedList.Callback();
+ method @Deprecated public abstract void onChanged(int position, int count);
+ method @Deprecated public abstract void onInserted(int position, int count);
+ method @Deprecated public abstract void onRemoved(int position, int count);
+ }
+
+ @Deprecated public static final class PagedList.Config {
+ field @Deprecated public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+ field @Deprecated public final boolean enablePlaceholders;
+ field @Deprecated public final int initialLoadSizeHint;
+ field @Deprecated public final int maxSize;
+ field @Deprecated public final int pageSize;
+ field @Deprecated public final int prefetchDistance;
+ }
+
+ @Deprecated public static final class PagedList.Config.Builder {
+ ctor @Deprecated public PagedList.Config.Builder();
+ method @Deprecated public androidx.paging.PagedList.Config build();
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean enablePlaceholders);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(@IntRange(from=1) int initialLoadSizeHint);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setMaxSize(@IntRange(from=2) int maxSize);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setPageSize(@IntRange(from=1) int pageSize);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setPrefetchDistance(@IntRange(from=0) int prefetchDistance);
+ }
+
+ public final class PagedListConfigKt {
+ method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * androidx.paging.PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = 2147483647);
+ }
+
+ public final class PagedListKt {
+ method @Deprecated public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
+ }
+
+ public final class Pager<Key, Value> {
+ ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, androidx.paging.RemoteMediator<Key,Value>? remoteMediator, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ ctor public Pager(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ method public kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> getFlow();
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> flow;
+ }
+
+ public final class PagingConfig {
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize, int jumpThreshold);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
+ ctor public PagingConfig(int pageSize);
+ field public static final androidx.paging.PagingConfig.Companion Companion;
+ field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+ field public final boolean enablePlaceholders;
+ field public final int initialLoadSize;
+ field public final int jumpThreshold;
+ field public final int maxSize;
+ field public final int pageSize;
+ field public final int prefetchDistance;
+ }
+
+ public static final class PagingConfig.Companion {
+ }
+
+ public final class PagingData<T> {
+ method public static <T> androidx.paging.PagingData<T> empty();
+ method @CheckResult public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method @CheckResult public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
+ method @CheckResult public androidx.paging.PagingData<T> insertFooterItem(T item);
+ method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
+ method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+ field public static final androidx.paging.PagingData.Companion Companion;
+ }
+
+ public static final class PagingData.Companion {
+ method public <T> androidx.paging.PagingData<T> empty();
+ method @CheckResult public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
+ public final class PagingDataKt {
+ method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
+ public abstract class PagingSource<Key, Value> {
+ ctor public PagingSource();
+ method public final boolean getInvalid();
+ method public boolean getJumpingSupported();
+ method public boolean getKeyReuseSupported();
+ method @androidx.paging.ExperimentalPagingApi public Key? getRefreshKey(androidx.paging.PagingState<Key,Value> state);
+ method public void invalidate();
+ method public abstract suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+ method public final void registerInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ method public final void unregisterInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ property public final boolean invalid;
+ property public boolean jumpingSupported;
+ property public boolean keyReuseSupported;
+ }
+
+ public abstract static sealed class PagingSource.LoadParams<Key> {
+ method public abstract Key? getKey();
+ method public final int getLoadSize();
+ method @Deprecated public final int getPageSize();
+ method public final boolean getPlaceholdersEnabled();
+ property public abstract Key? key;
+ }
+
+ public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled);
+ method public Key getKey();
+ }
+
+ public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled);
+ method public Key getKey();
+ }
+
+ public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled);
+ method public Key? getKey();
+ }
+
+ public abstract static sealed class PagingSource.LoadResult<Key, Value> {
+ }
+
+ public static final class PagingSource.LoadResult.Error<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+ ctor public PagingSource.LoadResult.Error(Throwable throwable);
+ method public Throwable component1();
+ method public androidx.paging.PagingSource.LoadResult.Error<Key,Value> copy(Throwable throwable);
+ method public Throwable getThrowable();
+ }
+
+ public static final class PagingSource.LoadResult.Page<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+ ctor public PagingSource.LoadResult.Page(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, @IntRange(from=null) int itemsBefore, @IntRange(from=null) int itemsAfter);
+ method public java.util.List<Value> component1();
+ method public Key? component2();
+ method public Key? component3();
+ method public int component4();
+ method public int component5();
+ method public androidx.paging.PagingSource.LoadResult.Page<Key,Value> copy(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, int itemsBefore, int itemsAfter);
+ method public java.util.List<Value> getData();
+ method public int getItemsAfter();
+ method public int getItemsBefore();
+ method public Key? getNextKey();
+ method public Key? getPrevKey();
+ field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
+ field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
+ }
+
+ public static final class PagingSource.LoadResult.Page.Companion {
+ }
+
+ public final class PagingSourceKt {
+ }
+
+ public final class PagingState<Key, Value> {
+ method public Value? closestItemToPosition(int anchorPosition);
+ method public androidx.paging.PagingSource.LoadResult.Page<Key,Value>? closestPageToPosition(int anchorPosition);
+ method public Value? firstItemOrNull();
+ method public Integer? getAnchorPosition();
+ method public androidx.paging.PagingConfig getConfig();
+ method public java.util.List<androidx.paging.PagingSource.LoadResult.Page<Key,Value>> getPages();
+ method public boolean isEmpty();
+ method public Value? lastItemOrNull();
+ }
+
+ @Deprecated public abstract class PositionalDataSource<T> extends androidx.paging.DataSource<java.lang.Integer,T> {
+ ctor @Deprecated public PositionalDataSource();
+ method @Deprecated public static final int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams params, int totalCount);
+ method @Deprecated public static final int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams params, int initialLoadPosition, int totalCount);
+ method @Deprecated @WorkerThread public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+ method @Deprecated @WorkerThread public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T,V> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(kotlin.jvm.functions.Function1<? super T,? extends V> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>,java.util.List<V>> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends T>,? extends java.util.List<? extends V>> function);
+ }
+
+ @Deprecated public abstract static class PositionalDataSource.LoadInitialCallback<T> {
+ ctor @Deprecated public PositionalDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position, int totalCount);
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position);
+ }
+
+ @Deprecated public static class PositionalDataSource.LoadInitialParams {
+ ctor @Deprecated public PositionalDataSource.LoadInitialParams(int requestedStartPosition, int requestedLoadSize, int pageSize, boolean placeholdersEnabled);
+ field @Deprecated public final int pageSize;
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final int requestedLoadSize;
+ field @Deprecated public final int requestedStartPosition;
+ }
+
+ @Deprecated public abstract static class PositionalDataSource.LoadRangeCallback<T> {
+ ctor @Deprecated public PositionalDataSource.LoadRangeCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data);
+ }
+
+ @Deprecated public static class PositionalDataSource.LoadRangeParams {
+ ctor @Deprecated public PositionalDataSource.LoadRangeParams(int startPosition, int loadSize);
+ field @Deprecated public final int loadSize;
+ field @Deprecated public final int startPosition;
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class RemoteMediator<Key, Value> {
+ ctor public RemoteMediator();
+ method public suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> $completion);
+ method public abstract suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ }
+
+ public enum RemoteMediator.InitializeAction {
+ method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.RemoteMediator.InitializeAction[] values();
+ enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
+ enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
+ }
+
+ public abstract static sealed class RemoteMediator.MediatorResult {
+ }
+
+ public static final class RemoteMediator.MediatorResult.Error extends androidx.paging.RemoteMediator.MediatorResult {
+ ctor public RemoteMediator.MediatorResult.Error(Throwable throwable);
+ method public Throwable getThrowable();
+ }
+
+ public static final class RemoteMediator.MediatorResult.Success extends androidx.paging.RemoteMediator.MediatorResult {
+ ctor public RemoteMediator.MediatorResult.Success(boolean endOfPaginationReached);
+ method public boolean endOfPaginationReached();
+ }
+
+ public final class SeparatorsKt {
+ }
+
+}
+
+package androidx.paging.multicast {
+
+ public final class ChannelManagerKt {
+ }
+
+}
+
diff --git a/paging/common/api/public_plus_experimental_current.txt b/paging/common/api/public_plus_experimental_current.txt
index a634c55..0776c3e 100644
--- a/paging/common/api/public_plus_experimental_current.txt
+++ b/paging/common/api/public_plus_experimental_current.txt
@@ -101,7 +101,7 @@
}
public static final class LoadState.Loading extends androidx.paging.LoadState {
- field public static final androidx.paging.LoadState.Loading! INSTANCE;
+ field public static final androidx.paging.LoadState.Loading INSTANCE;
}
public static final class LoadState.NotLoading extends androidx.paging.LoadState {
@@ -121,6 +121,8 @@
}
public enum LoadType {
+ method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.LoadType[] values();
enum_constant public static final androidx.paging.LoadType APPEND;
enum_constant public static final androidx.paging.LoadType PREPEND;
enum_constant public static final androidx.paging.LoadType REFRESH;
@@ -262,7 +264,7 @@
ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
ctor public PagingConfig(int pageSize);
- field public static final androidx.paging.PagingConfig.Companion! Companion;
+ field public static final androidx.paging.PagingConfig.Companion Companion;
field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
field public final boolean enablePlaceholders;
field public final int initialLoadSize;
@@ -283,7 +285,7 @@
method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
- field public static final androidx.paging.PagingData.Companion! Companion;
+ field public static final androidx.paging.PagingData.Companion Companion;
}
public static final class PagingData.Companion {
@@ -360,7 +362,7 @@
method public Key? getNextKey();
method public Key? getPrevKey();
field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
- field public static final androidx.paging.PagingSource.LoadResult.Page.Companion! Companion;
+ field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
}
public static final class PagingSource.LoadResult.Page.Companion {
@@ -424,6 +426,8 @@
}
public enum RemoteMediator.InitializeAction {
+ method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.RemoteMediator.InitializeAction[] values();
enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
}
diff --git a/paging/common/api/restricted_3.0.0-alpha03.txt b/paging/common/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..dd27c13
--- /dev/null
+++ b/paging/common/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,457 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ public final class CachedPagingDataKt {
+ method @CheckResult public static <T> kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>> cachedIn(kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ }
+
+ public final class CancelableChannelFlowKt {
+ }
+
+ public final class CombinedLoadStates {
+ ctor public CombinedLoadStates(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+ method public androidx.paging.LoadStates component1();
+ method public androidx.paging.LoadStates? component2();
+ method public androidx.paging.CombinedLoadStates copy(androidx.paging.LoadStates source, androidx.paging.LoadStates? mediator);
+ method public androidx.paging.LoadState getAppend();
+ method public androidx.paging.LoadStates? getMediator();
+ method public androidx.paging.LoadState getPrepend();
+ method public androidx.paging.LoadState getRefresh();
+ method public androidx.paging.LoadStates getSource();
+ property public final androidx.paging.LoadState append;
+ property public final androidx.paging.LoadState prepend;
+ property public final androidx.paging.LoadState refresh;
+ }
+
+ public abstract class DataSource<Key, Value> {
+ method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+ method @AnyThread public final void addInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ method @AnyThread public void invalidate();
+ method @WorkerThread public boolean isInvalid();
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method public <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback onInvalidatedCallback);
+ method @AnyThread public final void removeInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ property @WorkerThread public boolean isInvalid;
+ }
+
+ public abstract static class DataSource.Factory<Key, Value> {
+ ctor public DataSource.Factory();
+ method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = Dispatchers.IO);
+ method public final kotlin.jvm.functions.Function0<androidx.paging.PagingSource<Key,Value>> asPagingSourceFactory();
+ method public abstract androidx.paging.DataSource<Key,Value> create();
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ public static interface DataSource.InvalidatedCallback {
+ method @AnyThread public void onInvalidated();
+ }
+
+ @kotlin.RequiresOptIn public @interface ExperimentalPagingApi {
+ }
+
+ @Deprecated public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+ ctor @Deprecated public ItemKeyedDataSource();
+ method @Deprecated public abstract Key getKey(Value item);
+ method @Deprecated public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+ method @Deprecated public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadCallback<Value> callback);
+ method @Deprecated public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value> callback);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method @Deprecated public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ @Deprecated public abstract static class ItemKeyedDataSource.LoadCallback<Value> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data);
+ }
+
+ @Deprecated public abstract static class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback<Value> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount);
+ }
+
+ @Deprecated public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadInitialParams(Key? requestedInitialKey, int requestedLoadSize, boolean placeholdersEnabled);
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final Key? requestedInitialKey;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public static class ItemKeyedDataSource.LoadParams<Key> {
+ ctor @Deprecated public ItemKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+ field @Deprecated public final Key key;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ public abstract sealed class LoadState {
+ method public final boolean getEndOfPaginationReached();
+ }
+
+ public static final class LoadState.Error extends androidx.paging.LoadState {
+ ctor public LoadState.Error(Throwable error);
+ method public Throwable getError();
+ }
+
+ public static final class LoadState.Loading extends androidx.paging.LoadState {
+ field public static final androidx.paging.LoadState.Loading INSTANCE;
+ }
+
+ public static final class LoadState.NotLoading extends androidx.paging.LoadState {
+ ctor public LoadState.NotLoading(boolean endOfPaginationReached);
+ }
+
+ public final class LoadStates {
+ ctor public LoadStates(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+ method public androidx.paging.LoadState component1();
+ method public androidx.paging.LoadState component2();
+ method public androidx.paging.LoadState component3();
+ method public androidx.paging.LoadStates copy(androidx.paging.LoadState refresh, androidx.paging.LoadState prepend, androidx.paging.LoadState append);
+ method public androidx.paging.LoadState getAppend();
+ method public androidx.paging.LoadState getPrepend();
+ method public androidx.paging.LoadState getRefresh();
+ }
+
+ public enum LoadType {
+ method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.LoadType[] values();
+ enum_constant public static final androidx.paging.LoadType APPEND;
+ enum_constant public static final androidx.paging.LoadType PREPEND;
+ enum_constant public static final androidx.paging.LoadType REFRESH;
+ }
+
+ public final class PageEventKt {
+ }
+
+ @Deprecated public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key,Value> {
+ ctor @Deprecated public PageKeyedDataSource();
+ method @Deprecated public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+ method @Deprecated public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key> params, androidx.paging.PageKeyedDataSource.LoadCallback<Key,Value> callback);
+ method @Deprecated public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key> params, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key,Value> callback);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> map(kotlin.jvm.functions.Function1<? super Value,? extends ToValue> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>> function);
+ method @Deprecated public final <ToValue> androidx.paging.PageKeyedDataSource<Key,ToValue> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends Value>,? extends java.util.List<? extends ToValue>> function);
+ }
+
+ @Deprecated public abstract static class PageKeyedDataSource.LoadCallback<Key, Value> {
+ ctor @Deprecated public PageKeyedDataSource.LoadCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? adjacentPageKey);
+ }
+
+ @Deprecated public abstract static class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+ ctor @Deprecated public PageKeyedDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, int position, int totalCount, Key? previousPageKey, Key? nextPageKey);
+ method @Deprecated public abstract void onResult(java.util.List<? extends Value> data, Key? previousPageKey, Key? nextPageKey);
+ }
+
+ @Deprecated public static class PageKeyedDataSource.LoadInitialParams<Key> {
+ ctor @Deprecated public PageKeyedDataSource.LoadInitialParams(int requestedLoadSize, boolean placeholdersEnabled);
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public static class PageKeyedDataSource.LoadParams<Key> {
+ ctor @Deprecated public PageKeyedDataSource.LoadParams(Key key, int requestedLoadSize);
+ field @Deprecated public final Key key;
+ field @Deprecated public final int requestedLoadSize;
+ }
+
+ @Deprecated public abstract class PagedList<T> extends java.util.AbstractList<T> {
+ method @Deprecated public final void addWeakCallback(java.util.List<? extends T>? previousSnapshot, androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void addWeakCallback(androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void addWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public abstract void detach();
+ method @Deprecated public T? get(int index);
+ method @Deprecated public final androidx.paging.PagedList.Config getConfig();
+ method @Deprecated public final androidx.paging.DataSource<?,T> getDataSource();
+ method @Deprecated public abstract Object? getLastKey();
+ method @Deprecated public final int getLoadedCount();
+ method @Deprecated public final int getPositionOffset();
+ method @Deprecated public int getSize();
+ method @Deprecated public abstract boolean isDetached();
+ method @Deprecated public boolean isImmutable();
+ method @Deprecated public final void loadAround(int index);
+ method @Deprecated public final void removeWeakCallback(androidx.paging.PagedList.Callback callback);
+ method @Deprecated public final void removeWeakLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void retry();
+ method @Deprecated public final java.util.List<T> snapshot();
+ property @Deprecated public final androidx.paging.DataSource<?,T> dataSource;
+ property public abstract boolean isDetached;
+ property public boolean isImmutable;
+ property public abstract Object? lastKey;
+ property public final int loadedCount;
+ property public final int positionOffset;
+ property public int size;
+ }
+
+ @Deprecated @MainThread public abstract static class PagedList.BoundaryCallback<T> {
+ ctor @Deprecated public PagedList.BoundaryCallback();
+ method @Deprecated public void onItemAtEndLoaded(T itemAtEnd);
+ method @Deprecated public void onItemAtFrontLoaded(T itemAtFront);
+ method @Deprecated public void onZeroItemsLoaded();
+ }
+
+ @Deprecated public static final class PagedList.Builder<Key, Value> {
+ ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.DataSource<Key,Value> dataSource, int pageSize);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public PagedList.Builder(androidx.paging.PagingSource<Key,Value> pagingSource, androidx.paging.PagingSource.LoadResult.Page<Key,Value> initialPage, int pageSize);
+ method @Deprecated public androidx.paging.PagedList<Value> build();
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchDispatcher(kotlinx.coroutines.CoroutineDispatcher fetchDispatcher);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setInitialKey(Key? initialKey);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyDispatcher(kotlinx.coroutines.CoroutineDispatcher notifyDispatcher);
+ method @Deprecated public androidx.paging.PagedList.Builder<Key,Value> setNotifyExecutor(java.util.concurrent.Executor notifyExecutor);
+ }
+
+ @Deprecated public abstract static class PagedList.Callback {
+ ctor @Deprecated public PagedList.Callback();
+ method @Deprecated public abstract void onChanged(int position, int count);
+ method @Deprecated public abstract void onInserted(int position, int count);
+ method @Deprecated public abstract void onRemoved(int position, int count);
+ }
+
+ @Deprecated public static final class PagedList.Config {
+ field @Deprecated public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+ field @Deprecated public final boolean enablePlaceholders;
+ field @Deprecated public final int initialLoadSizeHint;
+ field @Deprecated public final int maxSize;
+ field @Deprecated public final int pageSize;
+ field @Deprecated public final int prefetchDistance;
+ }
+
+ @Deprecated public static final class PagedList.Config.Builder {
+ ctor @Deprecated public PagedList.Config.Builder();
+ method @Deprecated public androidx.paging.PagedList.Config build();
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean enablePlaceholders);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(@IntRange(from=1) int initialLoadSizeHint);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setMaxSize(@IntRange(from=2) int maxSize);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setPageSize(@IntRange(from=1) int pageSize);
+ method @Deprecated public androidx.paging.PagedList.Config.Builder setPrefetchDistance(@IntRange(from=0) int prefetchDistance);
+ }
+
+ public final class PagedListConfigKt {
+ method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * androidx.paging.PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = 2147483647);
+ }
+
+ public final class PagedListKt {
+ method @Deprecated public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
+ }
+
+ public final class Pager<Key, Value> {
+ ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, androidx.paging.RemoteMediator<Key,Value>? remoteMediator, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ ctor public Pager(androidx.paging.PagingConfig config, Key? initialKey, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ ctor public Pager(androidx.paging.PagingConfig config, kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory);
+ method public kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> getFlow();
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.PagingData<Value>> flow;
+ }
+
+ public final class PagingConfig {
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize, int jumpThreshold);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize, @IntRange(from=null) int maxSize);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders, @IntRange(from=null) int initialLoadSize);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
+ ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
+ ctor public PagingConfig(int pageSize);
+ field public static final androidx.paging.PagingConfig.Companion Companion;
+ field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
+ field public final boolean enablePlaceholders;
+ field public final int initialLoadSize;
+ field public final int jumpThreshold;
+ field public final int maxSize;
+ field public final int pageSize;
+ field public final int prefetchDistance;
+ }
+
+ public static final class PagingConfig.Companion {
+ }
+
+ public final class PagingData<T> {
+ method public static <T> androidx.paging.PagingData<T> empty();
+ method @CheckResult public androidx.paging.PagingData<T> filter(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
+ method @CheckResult public <R> androidx.paging.PagingData<R> flatMap(kotlin.jvm.functions.Function1<? super T,? extends java.lang.Iterable<? extends R>> transform);
+ method @CheckResult public androidx.paging.PagingData<T> insertFooterItem(T item);
+ method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
+ method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
+ field public static final androidx.paging.PagingData.Companion Companion;
+ }
+
+ public static final class PagingData.Companion {
+ method public <T> androidx.paging.PagingData<T> empty();
+ method @CheckResult public <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
+ public final class PagingDataKt {
+ method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T>, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
+ }
+
+ public abstract class PagingSource<Key, Value> {
+ ctor public PagingSource();
+ method public final boolean getInvalid();
+ method public boolean getJumpingSupported();
+ method public boolean getKeyReuseSupported();
+ method @androidx.paging.ExperimentalPagingApi public Key? getRefreshKey(androidx.paging.PagingState<Key,Value> state);
+ method public void invalidate();
+ method public abstract suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+ method public final void registerInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ method public final void unregisterInvalidatedCallback(kotlin.jvm.functions.Function0<kotlin.Unit> onInvalidatedCallback);
+ property public final boolean invalid;
+ property public boolean jumpingSupported;
+ property public boolean keyReuseSupported;
+ }
+
+ public abstract static sealed class PagingSource.LoadParams<Key> {
+ method public abstract Key? getKey();
+ method public final int getLoadSize();
+ method @Deprecated public final int getPageSize();
+ method public final boolean getPlaceholdersEnabled();
+ property public abstract Key? key;
+ }
+
+ public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled);
+ method public Key getKey();
+ }
+
+ public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled);
+ method public Key getKey();
+ }
+
+ public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+ ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+ ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled);
+ method public Key? getKey();
+ }
+
+ public abstract static sealed class PagingSource.LoadResult<Key, Value> {
+ }
+
+ public static final class PagingSource.LoadResult.Error<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+ ctor public PagingSource.LoadResult.Error(Throwable throwable);
+ method public Throwable component1();
+ method public androidx.paging.PagingSource.LoadResult.Error<Key,Value> copy(Throwable throwable);
+ method public Throwable getThrowable();
+ }
+
+ public static final class PagingSource.LoadResult.Page<Key, Value> extends androidx.paging.PagingSource.LoadResult<Key,Value> {
+ ctor public PagingSource.LoadResult.Page(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, @IntRange(from=null) int itemsBefore, @IntRange(from=null) int itemsAfter);
+ method public java.util.List<Value> component1();
+ method public Key? component2();
+ method public Key? component3();
+ method public int component4();
+ method public int component5();
+ method public androidx.paging.PagingSource.LoadResult.Page<Key,Value> copy(java.util.List<? extends Value> data, Key? prevKey, Key? nextKey, int itemsBefore, int itemsAfter);
+ method public java.util.List<Value> getData();
+ method public int getItemsAfter();
+ method public int getItemsBefore();
+ method public Key? getNextKey();
+ method public Key? getPrevKey();
+ field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
+ field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
+ }
+
+ public static final class PagingSource.LoadResult.Page.Companion {
+ }
+
+ public final class PagingSourceKt {
+ }
+
+ public final class PagingState<Key, Value> {
+ method public Value? closestItemToPosition(int anchorPosition);
+ method public androidx.paging.PagingSource.LoadResult.Page<Key,Value>? closestPageToPosition(int anchorPosition);
+ method public Value? firstItemOrNull();
+ method public Integer? getAnchorPosition();
+ method public androidx.paging.PagingConfig getConfig();
+ method public java.util.List<androidx.paging.PagingSource.LoadResult.Page<Key,Value>> getPages();
+ method public boolean isEmpty();
+ method public Value? lastItemOrNull();
+ }
+
+ @Deprecated public abstract class PositionalDataSource<T> extends androidx.paging.DataSource<java.lang.Integer,T> {
+ ctor @Deprecated public PositionalDataSource();
+ method @Deprecated public static final int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams params, int totalCount);
+ method @Deprecated public static final int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams params, int initialLoadPosition, int totalCount);
+ method @Deprecated @WorkerThread public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+ method @Deprecated @WorkerThread public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T,V> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> map(kotlin.jvm.functions.Function1<? super T,? extends V> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>,java.util.List<V>> function);
+ method @Deprecated public final <V> androidx.paging.PositionalDataSource<V> mapByPage(kotlin.jvm.functions.Function1<? super java.util.List<? extends T>,? extends java.util.List<? extends V>> function);
+ }
+
+ @Deprecated public abstract static class PositionalDataSource.LoadInitialCallback<T> {
+ ctor @Deprecated public PositionalDataSource.LoadInitialCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position, int totalCount);
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data, int position);
+ }
+
+ @Deprecated public static class PositionalDataSource.LoadInitialParams {
+ ctor @Deprecated public PositionalDataSource.LoadInitialParams(int requestedStartPosition, int requestedLoadSize, int pageSize, boolean placeholdersEnabled);
+ field @Deprecated public final int pageSize;
+ field @Deprecated public final boolean placeholdersEnabled;
+ field @Deprecated public final int requestedLoadSize;
+ field @Deprecated public final int requestedStartPosition;
+ }
+
+ @Deprecated public abstract static class PositionalDataSource.LoadRangeCallback<T> {
+ ctor @Deprecated public PositionalDataSource.LoadRangeCallback();
+ method @Deprecated public abstract void onResult(java.util.List<? extends T> data);
+ }
+
+ @Deprecated public static class PositionalDataSource.LoadRangeParams {
+ ctor @Deprecated public PositionalDataSource.LoadRangeParams(int startPosition, int loadSize);
+ field @Deprecated public final int loadSize;
+ field @Deprecated public final int startPosition;
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class RemoteMediator<Key, Value> {
+ ctor public RemoteMediator();
+ method public suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> $completion);
+ method public abstract suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ }
+
+ public enum RemoteMediator.InitializeAction {
+ method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.RemoteMediator.InitializeAction[] values();
+ enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
+ enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
+ }
+
+ public abstract static sealed class RemoteMediator.MediatorResult {
+ }
+
+ public static final class RemoteMediator.MediatorResult.Error extends androidx.paging.RemoteMediator.MediatorResult {
+ ctor public RemoteMediator.MediatorResult.Error(Throwable throwable);
+ method public Throwable getThrowable();
+ }
+
+ public static final class RemoteMediator.MediatorResult.Success extends androidx.paging.RemoteMediator.MediatorResult {
+ ctor public RemoteMediator.MediatorResult.Success(boolean endOfPaginationReached);
+ method public boolean endOfPaginationReached();
+ }
+
+ public final class SeparatorsKt {
+ }
+
+}
+
+package androidx.paging.multicast {
+
+ public final class ChannelManagerKt {
+ }
+
+}
+
diff --git a/paging/common/api/restricted_current.txt b/paging/common/api/restricted_current.txt
index 351532f..dd27c13 100644
--- a/paging/common/api/restricted_current.txt
+++ b/paging/common/api/restricted_current.txt
@@ -100,7 +100,7 @@
}
public static final class LoadState.Loading extends androidx.paging.LoadState {
- field public static final androidx.paging.LoadState.Loading! INSTANCE;
+ field public static final androidx.paging.LoadState.Loading INSTANCE;
}
public static final class LoadState.NotLoading extends androidx.paging.LoadState {
@@ -119,6 +119,8 @@
}
public enum LoadType {
+ method public static androidx.paging.LoadType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.LoadType[] values();
enum_constant public static final androidx.paging.LoadType APPEND;
enum_constant public static final androidx.paging.LoadType PREPEND;
enum_constant public static final androidx.paging.LoadType REFRESH;
@@ -260,7 +262,7 @@
ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance, boolean enablePlaceholders);
ctor public PagingConfig(int pageSize, @IntRange(from=null) int prefetchDistance);
ctor public PagingConfig(int pageSize);
- field public static final androidx.paging.PagingConfig.Companion! Companion;
+ field public static final androidx.paging.PagingConfig.Companion Companion;
field public static final int MAX_SIZE_UNBOUNDED = 2147483647; // 0x7fffffff
field public final boolean enablePlaceholders;
field public final int initialLoadSize;
@@ -281,7 +283,7 @@
method @CheckResult public androidx.paging.PagingData<T> insertHeaderItem(T item);
method @CheckResult public static <T extends R, R> androidx.paging.PagingData<R> insertSeparators(androidx.paging.PagingData<T> pagingData, kotlin.jvm.functions.Function2<? super T,? super T,? extends R> generator);
method @CheckResult public <R> androidx.paging.PagingData<R> map(kotlin.jvm.functions.Function1<? super T,? extends R> transform);
- field public static final androidx.paging.PagingData.Companion! Companion;
+ field public static final androidx.paging.PagingData.Companion Companion;
}
public static final class PagingData.Companion {
@@ -358,7 +360,7 @@
method public Key? getNextKey();
method public Key? getPrevKey();
field public static final int COUNT_UNDEFINED = -2147483648; // 0x80000000
- field public static final androidx.paging.PagingSource.LoadResult.Page.Companion! Companion;
+ field public static final androidx.paging.PagingSource.LoadResult.Page.Companion Companion;
}
public static final class PagingSource.LoadResult.Page.Companion {
@@ -422,6 +424,8 @@
}
public enum RemoteMediator.InitializeAction {
+ method public static androidx.paging.RemoteMediator.InitializeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.paging.RemoteMediator.InitializeAction[] values();
enum_constant public static final androidx.paging.RemoteMediator.InitializeAction LAUNCH_INITIAL_REFRESH;
enum_constant public static final androidx.paging.RemoteMediator.InitializeAction SKIP_INITIAL_REFRESH;
}
diff --git a/paging/common/ktx/api/3.0.0-alpha03.txt b/paging/common/ktx/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/common/ktx/api/3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/common/ktx/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/common/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/common/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/common/ktx/api/restricted_3.0.0-alpha03.txt b/paging/common/ktx/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/common/ktx/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
index 5cc790b..153c632 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
@@ -92,7 +92,8 @@
@OptIn(ExperimentalCoroutinesApi::class)
val pageEventFlow: Flow<PageEvent<Value>> = cancelableChannelFlow(pageEventChannelFlowJob) {
check(pageEventChCollected.compareAndSet(false, true)) {
- "cannot collect twice from pager"
+ "Attempt to collect twice from pageEventFlow, which is an illegal operation. Did you " +
+ "forget to call Flow<PagingData<*>>.cachedIn(coroutineScope)?"
}
// Start collection on pageEventCh, which the rest of this class uses to send PageEvents
diff --git a/paging/guava/api/3.0.0-alpha03.txt b/paging/guava/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..a440d78
--- /dev/null
+++ b/paging/guava/api/3.0.0-alpha03.txt
@@ -0,0 +1,19 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ public abstract class ListenableFuturePagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+ ctor public ListenableFuturePagingSource();
+ method public suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> p, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> $completion);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.PagingSource.LoadResult<Key,Value>> loadFuture(androidx.paging.PagingSource.LoadParams<Key> params);
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class ListenableFutureRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+ ctor public ListenableFutureRemoteMediator();
+ method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.InitializeAction> initializeFuture();
+ method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.MediatorResult> loadFuture(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+ }
+
+}
+
diff --git a/paging/guava/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/guava/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..a440d78
--- /dev/null
+++ b/paging/guava/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,19 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ public abstract class ListenableFuturePagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+ ctor public ListenableFuturePagingSource();
+ method public suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> p, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> $completion);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.PagingSource.LoadResult<Key,Value>> loadFuture(androidx.paging.PagingSource.LoadParams<Key> params);
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class ListenableFutureRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+ ctor public ListenableFutureRemoteMediator();
+ method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.InitializeAction> initializeFuture();
+ method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.MediatorResult> loadFuture(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+ }
+
+}
+
diff --git a/paging/guava/api/res-3.0.0-alpha03.txt b/paging/guava/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/guava/api/res-3.0.0-alpha03.txt
diff --git a/paging/guava/api/restricted_3.0.0-alpha03.txt b/paging/guava/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..a440d78
--- /dev/null
+++ b/paging/guava/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,19 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ public abstract class ListenableFuturePagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+ ctor public ListenableFuturePagingSource();
+ method public suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> p, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> $completion);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.PagingSource.LoadResult<Key,Value>> loadFuture(androidx.paging.PagingSource.LoadParams<Key> params);
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class ListenableFutureRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+ ctor public ListenableFutureRemoteMediator();
+ method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.InitializeAction> initializeFuture();
+ method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.paging.RemoteMediator.MediatorResult> loadFuture(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+ }
+
+}
+
diff --git a/paging/runtime/api/3.0.0-alpha03.txt b/paging/runtime/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..072f3457
--- /dev/null
+++ b/paging/runtime/api/3.0.0-alpha03.txt
@@ -0,0 +1,133 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ @Deprecated public class AsyncPagedListDiffer<T> {
+ ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter<?> adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback listUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+ method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void addPagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+ method @Deprecated public final void addPagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+ method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+ method @Deprecated public T? getItem(int index);
+ method @Deprecated public int getItemCount();
+ method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void removePagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+ method @Deprecated public final void removePagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+ property public androidx.paging.PagedList<T>? currentList;
+ property public int itemCount;
+ }
+
+ @Deprecated public static interface AsyncPagedListDiffer.PagedListListener<T> {
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+ }
+
+ public final class AsyncPagingDataDiffer<T> {
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback);
+ method @androidx.paging.ExperimentalPagingApi public void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+ method public T? getItem(int index);
+ method public int getItemCount();
+ method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+ method public void refresh();
+ method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public void retry();
+ method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+ property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+ property public final int itemCount;
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+ }
+
+ @Deprecated public final class LivePagedListBuilder<Key, Value> {
+ ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
+ ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
+ method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+ }
+
+ public final class LivePagedListKt {
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+ }
+
+ public abstract class LoadStateAdapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor public LoadStateAdapter();
+ method public boolean displayLoadStateAsItem(androidx.paging.LoadState loadState);
+ method public final int getItemCount();
+ method public final int getItemViewType(int position);
+ method public final androidx.paging.LoadState getLoadState();
+ method public int getStateViewType(androidx.paging.LoadState loadState);
+ method public final void onBindViewHolder(VH holder, int position);
+ method public abstract void onBindViewHolder(VH holder, androidx.paging.LoadState loadState);
+ method public final VH onCreateViewHolder(android.view.ViewGroup parent, int viewType);
+ method public abstract VH onCreateViewHolder(android.view.ViewGroup parent, androidx.paging.LoadState loadState);
+ method public final void setLoadState(androidx.paging.LoadState loadState);
+ property public final androidx.paging.LoadState loadState;
+ }
+
+ public final class NullPaddedListDiffHelperKt {
+ }
+
+ @Deprecated public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+ method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+ method @Deprecated protected T? getItem(int position);
+ method @Deprecated public int getItemCount();
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? currentList);
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+ method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+ property public androidx.paging.PagedList<T>? currentList;
+ }
+
+ public abstract class PagingDataAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ method @androidx.paging.ExperimentalPagingApi public final void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public final void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+ method protected final T? getItem(int position);
+ method public int getItemCount();
+ method public final long getItemId(int position);
+ method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+ method public final void refresh();
+ method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public final void retry();
+ method public final suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public final void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+ property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+ }
+
+ public final class PagingLiveData {
+ method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, androidx.lifecycle.Lifecycle lifecycle);
+ method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagingData<Value>> getLiveData(androidx.paging.Pager<Key,Value>);
+ }
+
+}
+
diff --git a/paging/runtime/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/runtime/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..072f3457
--- /dev/null
+++ b/paging/runtime/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,133 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ @Deprecated public class AsyncPagedListDiffer<T> {
+ ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter<?> adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback listUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+ method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void addPagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+ method @Deprecated public final void addPagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+ method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+ method @Deprecated public T? getItem(int index);
+ method @Deprecated public int getItemCount();
+ method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void removePagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+ method @Deprecated public final void removePagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+ property public androidx.paging.PagedList<T>? currentList;
+ property public int itemCount;
+ }
+
+ @Deprecated public static interface AsyncPagedListDiffer.PagedListListener<T> {
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+ }
+
+ public final class AsyncPagingDataDiffer<T> {
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback);
+ method @androidx.paging.ExperimentalPagingApi public void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+ method public T? getItem(int index);
+ method public int getItemCount();
+ method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+ method public void refresh();
+ method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public void retry();
+ method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+ property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+ property public final int itemCount;
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+ }
+
+ @Deprecated public final class LivePagedListBuilder<Key, Value> {
+ ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
+ ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
+ method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+ }
+
+ public final class LivePagedListKt {
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+ }
+
+ public abstract class LoadStateAdapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor public LoadStateAdapter();
+ method public boolean displayLoadStateAsItem(androidx.paging.LoadState loadState);
+ method public final int getItemCount();
+ method public final int getItemViewType(int position);
+ method public final androidx.paging.LoadState getLoadState();
+ method public int getStateViewType(androidx.paging.LoadState loadState);
+ method public final void onBindViewHolder(VH holder, int position);
+ method public abstract void onBindViewHolder(VH holder, androidx.paging.LoadState loadState);
+ method public final VH onCreateViewHolder(android.view.ViewGroup parent, int viewType);
+ method public abstract VH onCreateViewHolder(android.view.ViewGroup parent, androidx.paging.LoadState loadState);
+ method public final void setLoadState(androidx.paging.LoadState loadState);
+ property public final androidx.paging.LoadState loadState;
+ }
+
+ public final class NullPaddedListDiffHelperKt {
+ }
+
+ @Deprecated public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+ method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+ method @Deprecated protected T? getItem(int position);
+ method @Deprecated public int getItemCount();
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? currentList);
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+ method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+ property public androidx.paging.PagedList<T>? currentList;
+ }
+
+ public abstract class PagingDataAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ method @androidx.paging.ExperimentalPagingApi public final void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public final void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+ method protected final T? getItem(int position);
+ method public int getItemCount();
+ method public final long getItemId(int position);
+ method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+ method public final void refresh();
+ method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public final void retry();
+ method public final suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public final void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+ property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+ }
+
+ public final class PagingLiveData {
+ method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, androidx.lifecycle.Lifecycle lifecycle);
+ method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagingData<Value>> getLiveData(androidx.paging.Pager<Key,Value>);
+ }
+
+}
+
diff --git a/paging/runtime/api/res-3.0.0-alpha03.txt b/paging/runtime/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/runtime/api/res-3.0.0-alpha03.txt
diff --git a/paging/runtime/api/restricted_3.0.0-alpha03.txt b/paging/runtime/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..072f3457
--- /dev/null
+++ b/paging/runtime/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,133 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ @Deprecated public class AsyncPagedListDiffer<T> {
+ ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter<?> adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ ctor @Deprecated public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback listUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+ method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void addPagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+ method @Deprecated public final void addPagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+ method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+ method @Deprecated public T? getItem(int index);
+ method @Deprecated public int getItemCount();
+ method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void removePagedListListener(androidx.paging.AsyncPagedListDiffer.PagedListListener<T> listener);
+ method @Deprecated public final void removePagedListListener(kotlin.jvm.functions.Function2<? super androidx.paging.PagedList<T>,? super androidx.paging.PagedList<T>,kotlin.Unit> callback);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+ property public androidx.paging.PagedList<T>? currentList;
+ property public int itemCount;
+ }
+
+ @Deprecated public static interface AsyncPagedListDiffer.PagedListListener<T> {
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+ }
+
+ public final class AsyncPagingDataDiffer<T> {
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+ ctor public AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, androidx.recyclerview.widget.ListUpdateCallback updateCallback);
+ method @androidx.paging.ExperimentalPagingApi public void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+ method public T? getItem(int index);
+ method public int getItemCount();
+ method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+ method public void refresh();
+ method @androidx.paging.ExperimentalPagingApi public void removeDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public void retry();
+ method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+ property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+ property public final int itemCount;
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+ }
+
+ @Deprecated public final class LivePagedListBuilder<Key, Value> {
+ ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
+ ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public LivePagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
+ method @Deprecated public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setCoroutineScope(kotlinx.coroutines.CoroutineScope coroutineScope);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setFetchExecutor(java.util.concurrent.Executor fetchExecutor);
+ method @Deprecated public androidx.paging.LivePagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+ }
+
+ public final class LivePagedListKt {
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, java.util.concurrent.Executor fetchExecutor = ArchTaskExecutor.getIOThreadExecutor());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+ method @Deprecated public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> toLiveData(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, kotlinx.coroutines.CoroutineScope coroutineScope = GlobalScope, kotlinx.coroutines.CoroutineDispatcher fetchDispatcher = ArchTaskExecutor.getIOThreadExecutor().asCoroutineDispatcher());
+ }
+
+ public abstract class LoadStateAdapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor public LoadStateAdapter();
+ method public boolean displayLoadStateAsItem(androidx.paging.LoadState loadState);
+ method public final int getItemCount();
+ method public final int getItemViewType(int position);
+ method public final androidx.paging.LoadState getLoadState();
+ method public int getStateViewType(androidx.paging.LoadState loadState);
+ method public final void onBindViewHolder(VH holder, int position);
+ method public abstract void onBindViewHolder(VH holder, androidx.paging.LoadState loadState);
+ method public final VH onCreateViewHolder(android.view.ViewGroup parent, int viewType);
+ method public abstract VH onCreateViewHolder(android.view.ViewGroup parent, androidx.paging.LoadState loadState);
+ method public final void setLoadState(androidx.paging.LoadState loadState);
+ property public final androidx.paging.LoadState loadState;
+ }
+
+ public final class NullPaddedListDiffHelperKt {
+ }
+
+ @Deprecated public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ ctor @Deprecated protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T> config);
+ method @Deprecated public void addLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public androidx.paging.PagedList<T>? getCurrentList();
+ method @Deprecated protected T? getItem(int position);
+ method @Deprecated public int getItemCount();
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? currentList);
+ method @Deprecated public void onCurrentListChanged(androidx.paging.PagedList<T>? previousList, androidx.paging.PagedList<T>? currentList);
+ method @Deprecated public void removeLoadStateListener(kotlin.jvm.functions.Function2<? super androidx.paging.LoadType,? super androidx.paging.LoadState,kotlin.Unit> listener);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList);
+ method @Deprecated public void submitList(androidx.paging.PagedList<T>? pagedList, Runnable? commitCallback);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+ method @Deprecated public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+ property public androidx.paging.PagedList<T>? currentList;
+ }
+
+ public abstract class PagingDataAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter<VH> {
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher, kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
+ ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
+ method @androidx.paging.ExperimentalPagingApi public final void addDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public final void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> getDataRefreshFlow();
+ method protected final T? getItem(int position);
+ method public int getItemCount();
+ method public final long getItemId(int position);
+ method public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+ method public final void refresh();
+ method @androidx.paging.ExperimentalPagingApi public final void removeDataRefreshListener(kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> listener);
+ method public final void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
+ method public final void retry();
+ method public final suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+ method public final void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateFooter(androidx.paging.LoadStateAdapter<?> footer);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeader(androidx.paging.LoadStateAdapter<?> header);
+ method public final androidx.recyclerview.widget.ConcatAdapter withLoadStateHeaderAndFooter(androidx.paging.LoadStateAdapter<?> header, androidx.paging.LoadStateAdapter<?> footer);
+ property public final kotlinx.coroutines.flow.Flow<java.lang.Boolean> dataRefreshFlow;
+ property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
+ }
+
+ public final class PagingLiveData {
+ method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, androidx.lifecycle.Lifecycle lifecycle);
+ method public static <T> androidx.lifecycle.LiveData<androidx.paging.PagingData<T>> cachedIn(androidx.lifecycle.LiveData<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <Key, Value> androidx.lifecycle.LiveData<androidx.paging.PagingData<Value>> getLiveData(androidx.paging.Pager<Key,Value>);
+ }
+
+}
+
diff --git a/paging/runtime/ktx/api/3.0.0-alpha03.txt b/paging/runtime/ktx/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/runtime/ktx/api/3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/runtime/ktx/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/runtime/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/runtime/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/runtime/ktx/api/res-3.0.0-alpha03.txt b/paging/runtime/ktx/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/runtime/ktx/api/res-3.0.0-alpha03.txt
diff --git a/paging/runtime/ktx/api/restricted_3.0.0-alpha03.txt b/paging/runtime/ktx/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/runtime/ktx/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/rxjava2/api/3.0.0-alpha03.txt b/paging/rxjava2/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..4923f87
--- /dev/null
+++ b/paging/rxjava2/api/3.0.0-alpha03.txt
@@ -0,0 +1,54 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ @Deprecated public final class RxPagedListBuilder<Key, Value> {
+ ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
+ ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
+ method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+ method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+ }
+
+ public final class RxPagedListKt {
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ }
+
+}
+
+package androidx.paging.rxjava2 {
+
+ public final class PagingRx {
+ method public static <T> io.reactivex.Observable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Observable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <T> io.reactivex.Flowable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Flowable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagingData<Value>> getFlowable(androidx.paging.Pager<Key,Value>);
+ method public static <Key, Value> io.reactivex.Observable<androidx.paging.PagingData<Value>> getObservable(androidx.paging.Pager<Key,Value>);
+ }
+
+ public abstract class RxPagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+ ctor public RxPagingSource();
+ method public final suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+ method public abstract io.reactivex.Single<androidx.paging.PagingSource.LoadResult<Key,Value>> loadSingle(androidx.paging.PagingSource.LoadParams<Key> params);
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class RxRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+ ctor public RxRemoteMediator();
+ method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+ method public io.reactivex.Single<androidx.paging.RemoteMediator.InitializeAction> initializeSingle();
+ method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ method public abstract io.reactivex.Single<androidx.paging.RemoteMediator.MediatorResult> loadSingle(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+ }
+
+}
+
diff --git a/paging/rxjava2/api/api_lint.ignore b/paging/rxjava2/api/api_lint.ignore
index 153d977..43bf4f5 100644
--- a/paging/rxjava2/api/api_lint.ignore
+++ b/paging/rxjava2/api/api_lint.ignore
@@ -3,11 +3,3 @@
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.paging.RxPagedListBuilder.buildFlowable(io.reactivex.BackpressureStrategy)
BuilderSetStyle: androidx.paging.RxPagedListBuilder#buildObservable():
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.paging.RxPagedListBuilder.buildObservable()
-
-
-MissingBuildMethod: androidx.paging.RxPagedListBuilder:
- androidx.paging.RxPagedListBuilder does not declare a `build()` method, but builder classes are expected to
-
-
-TopLevelBuilder: androidx.paging.RxPagedListBuilder:
- Builder should be defined as inner class: androidx.paging.RxPagedListBuilder
diff --git a/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..4923f87
--- /dev/null
+++ b/paging/rxjava2/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1,54 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ @Deprecated public final class RxPagedListBuilder<Key, Value> {
+ ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
+ ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
+ method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+ method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+ }
+
+ public final class RxPagedListKt {
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ }
+
+}
+
+package androidx.paging.rxjava2 {
+
+ public final class PagingRx {
+ method public static <T> io.reactivex.Observable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Observable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <T> io.reactivex.Flowable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Flowable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagingData<Value>> getFlowable(androidx.paging.Pager<Key,Value>);
+ method public static <Key, Value> io.reactivex.Observable<androidx.paging.PagingData<Value>> getObservable(androidx.paging.Pager<Key,Value>);
+ }
+
+ public abstract class RxPagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+ ctor public RxPagingSource();
+ method public final suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+ method public abstract io.reactivex.Single<androidx.paging.PagingSource.LoadResult<Key,Value>> loadSingle(androidx.paging.PagingSource.LoadParams<Key> params);
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class RxRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+ ctor public RxRemoteMediator();
+ method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+ method public io.reactivex.Single<androidx.paging.RemoteMediator.InitializeAction> initializeSingle();
+ method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ method public abstract io.reactivex.Single<androidx.paging.RemoteMediator.MediatorResult> loadSingle(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+ }
+
+}
+
diff --git a/paging/rxjava2/api/res-3.0.0-alpha03.txt b/paging/rxjava2/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/rxjava2/api/res-3.0.0-alpha03.txt
diff --git a/paging/rxjava2/api/restricted_3.0.0-alpha03.txt b/paging/rxjava2/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..4923f87
--- /dev/null
+++ b/paging/rxjava2/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1,54 @@
+// Signature format: 3.0
+package androidx.paging {
+
+ @Deprecated public final class RxPagedListBuilder<Key, Value> {
+ ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public RxPagedListBuilder(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>> pagingSourceFactory, int pageSize);
+ ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, androidx.paging.PagedList.Config config);
+ ctor @Deprecated public RxPagedListBuilder(androidx.paging.DataSource.Factory<Key,Value> dataSourceFactory, int pageSize);
+ method @Deprecated public io.reactivex.Flowable<androidx.paging.PagedList<Value>> buildFlowable(io.reactivex.BackpressureStrategy backpressureStrategy);
+ method @Deprecated public io.reactivex.Observable<androidx.paging.PagedList<Value>> buildObservable();
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setFetchScheduler(io.reactivex.Scheduler scheduler);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setInitialLoadKey(Key? key);
+ method @Deprecated public androidx.paging.RxPagedListBuilder<Key,Value> setNotifyScheduler(io.reactivex.Scheduler scheduler);
+ }
+
+ public final class RxPagedListKt {
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagedList<Value>> toFlowable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null, io.reactivex.BackpressureStrategy backpressureStrategy = io.reactivex.BackpressureStrategy.LATEST);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(androidx.paging.DataSource.Factory<Key,Value>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, androidx.paging.PagedList.Config config, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ method @Deprecated public static <Key, Value> io.reactivex.Observable<androidx.paging.PagedList<Value>> toObservable(kotlin.jvm.functions.Function0<? extends androidx.paging.PagingSource<Key,Value>>, int pageSize, Key? initialLoadKey = null, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, io.reactivex.Scheduler? fetchScheduler = null, io.reactivex.Scheduler? notifyScheduler = null);
+ }
+
+}
+
+package androidx.paging.rxjava2 {
+
+ public final class PagingRx {
+ method public static <T> io.reactivex.Observable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Observable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <T> io.reactivex.Flowable<androidx.paging.PagingData<T>> cachedIn(io.reactivex.Flowable<androidx.paging.PagingData<T>>, kotlinx.coroutines.CoroutineScope scope);
+ method public static <Key, Value> io.reactivex.Flowable<androidx.paging.PagingData<Value>> getFlowable(androidx.paging.Pager<Key,Value>);
+ method public static <Key, Value> io.reactivex.Observable<androidx.paging.PagingData<Value>> getObservable(androidx.paging.Pager<Key,Value>);
+ }
+
+ public abstract class RxPagingSource<Key, Value> extends androidx.paging.PagingSource<Key,Value> {
+ ctor public RxPagingSource();
+ method public final suspend Object? load(androidx.paging.PagingSource.LoadParams<Key> params, kotlin.coroutines.Continuation<? super androidx.paging.PagingSource.LoadResult<Key,Value>> p);
+ method public abstract io.reactivex.Single<androidx.paging.PagingSource.LoadResult<Key,Value>> loadSingle(androidx.paging.PagingSource.LoadParams<Key> params);
+ }
+
+ @androidx.paging.ExperimentalPagingApi public abstract class RxRemoteMediator<Key, Value> extends androidx.paging.RemoteMediator<Key,Value> {
+ ctor public RxRemoteMediator();
+ method public final suspend Object? initialize(kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.InitializeAction> p);
+ method public io.reactivex.Single<androidx.paging.RemoteMediator.InitializeAction> initializeSingle();
+ method public final suspend Object? load(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state, kotlin.coroutines.Continuation<? super androidx.paging.RemoteMediator.MediatorResult> p);
+ method public abstract io.reactivex.Single<androidx.paging.RemoteMediator.MediatorResult> loadSingle(androidx.paging.LoadType loadType, androidx.paging.PagingState<Key,Value> state);
+ }
+
+}
+
diff --git a/paging/rxjava2/ktx/api/3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/rxjava2/ktx/api/3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/rxjava2/ktx/api/public_plus_experimental_3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/rxjava2/ktx/api/public_plus_experimental_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/paging/rxjava2/ktx/api/res-3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/res-3.0.0-alpha03.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paging/rxjava2/ktx/api/res-3.0.0-alpha03.txt
diff --git a/paging/rxjava2/ktx/api/restricted_3.0.0-alpha03.txt b/paging/rxjava2/ktx/api/restricted_3.0.0-alpha03.txt
new file mode 100644
index 0000000..da4f6cc
--- /dev/null
+++ b/paging/rxjava2/ktx/api/restricted_3.0.0-alpha03.txt
@@ -0,0 +1 @@
+// Signature format: 3.0
diff --git a/palette/palette/api/api_lint.ignore b/palette/palette/api/api_lint.ignore
index 162d7eb..85f67cb 100644
--- a/palette/palette/api/api_lint.ignore
+++ b/palette/palette/api/api_lint.ignore
@@ -1,8 +1,6 @@
// Baseline format: 1.0
BuilderSetStyle: androidx.palette.graphics.Palette.Builder#generate():
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.generate()
-BuilderSetStyle: androidx.palette.graphics.Palette.Builder#generate(androidx.palette.graphics.Palette.PaletteAsyncListener):
- Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.generate(androidx.palette.graphics.Palette.PaletteAsyncListener)
BuilderSetStyle: androidx.palette.graphics.Palette.Builder#maximumColorCount(int):
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.palette.graphics.Palette.Builder.maximumColorCount(int)
BuilderSetStyle: androidx.palette.graphics.Palette.Builder#resizeBitmapArea(int):
diff --git a/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml b/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml
index 96e0fb7..8653650 100644
--- a/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml
+++ b/recyclerview/recyclerview-benchmark/src/androidTest/AndroidManifest.xml
@@ -23,6 +23,9 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
<activity
android:name=".RecyclerViewActivity"
android:theme="@style/BenchmarkTheme"/>
diff --git a/room/benchmark/src/androidTest/AndroidManifest.xml b/room/benchmark/src/androidTest/AndroidManifest.xml
index aeadd7c..23bc3af 100644
--- a/room/benchmark/src/androidTest/AndroidManifest.xml
+++ b/room/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt b/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
new file mode 100644
index 0000000..fd9c3b2
--- /dev/null
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.solver
+
+import androidx.room.ext.RoomRxJava2TypeNames
+import androidx.room.ext.RxJava2TypeNames
+import androidx.room.processor.ProcessorErrors
+import com.squareup.javapoet.ClassName
+
+internal enum class RxType(
+ val version: RxVersion,
+ val className: ClassName,
+ val factoryMethodName: String? = null,
+ val canBeNull: Boolean = false
+) {
+ RX2_FLOWABLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.FLOWABLE,
+ factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE),
+ RX2_OBSERVABLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.OBSERVABLE,
+ factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE),
+ RX2_SINGLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.SINGLE),
+ RX2_MAYBE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.MAYBE,
+ canBeNull = true),
+ RX2_COMPLETABLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.COMPLETABLE);
+
+ fun isSingle() = this == RX2_SINGLE
+}
+
+internal enum class RxVersion(
+ val rxRoomClassName: ClassName,
+ val emptyResultExceptionClassName: ClassName,
+ val missingArtifactMessage: String
+) {
+ TWO(
+ rxRoomClassName = RoomRxJava2TypeNames.RX_ROOM,
+ emptyResultExceptionClassName = RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+ missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT),
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 07f17d0..dcb598e 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -36,17 +36,14 @@
import androidx.room.solver.binderprovider.InstantQueryResultBinderProvider
import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxFlowableQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxMaybeQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxObservableQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxSingleQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxCallableQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
import androidx.room.solver.prepared.binder.InstantPreparedQueryResultBinder
import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
import androidx.room.solver.prepared.binderprovider.GuavaListenableFuturePreparedQueryResultBinderProvider
import androidx.room.solver.prepared.binderprovider.InstantPreparedQueryResultBinderProvider
-import androidx.room.solver.prepared.binderprovider.RxCompletablePreparedQueryResultBinderProvider
-import androidx.room.solver.prepared.binderprovider.RxMaybePreparedQueryResultBinderProvider
-import androidx.room.solver.prepared.binderprovider.RxSinglePreparedQueryResultBinderProvider
+import androidx.room.solver.prepared.binderprovider.PreparedQueryResultBinderProvider
+import androidx.room.solver.prepared.binderprovider.RxPreparedQueryResultBinderProvider
import androidx.room.solver.prepared.result.PreparedQueryResultAdapter
import androidx.room.solver.query.parameter.ArrayQueryParameterAdapter
import androidx.room.solver.query.parameter.BasicQueryParameterAdapter
@@ -69,16 +66,14 @@
import androidx.room.solver.shortcut.binder.InsertMethodBinder
import androidx.room.solver.shortcut.binder.InstantDeleteOrUpdateMethodBinder
import androidx.room.solver.shortcut.binder.InstantInsertMethodBinder
+import androidx.room.solver.shortcut.binderprovider.DeleteOrUpdateMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureDeleteOrUpdateMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureInsertMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.InsertMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.InstantDeleteOrUpdateMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.InstantInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleInsertMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableDeleteOrUpdateMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableInsertMethodBinderProvider
import androidx.room.solver.shortcut.result.DeleteOrUpdateMethodAdapter
import androidx.room.solver.shortcut.result.InsertMethodAdapter
import androidx.room.solver.types.BoxedBooleanToBoxedIntConverter
@@ -169,44 +164,40 @@
}
}
- val queryResultBinderProviders = listOf(
- CursorQueryResultBinderProvider(context),
- LiveDataQueryResultBinderProvider(context),
- GuavaListenableFutureQueryResultBinderProvider(context),
- RxFlowableQueryResultBinderProvider(context),
- RxObservableQueryResultBinderProvider(context),
- RxMaybeQueryResultBinderProvider(context),
- RxSingleQueryResultBinderProvider(context),
- DataSourceQueryResultBinderProvider(context),
- DataSourceFactoryQueryResultBinderProvider(context),
- PagingSourceQueryResultBinderProvider(context),
- CoroutineFlowResultBinderProvider(context),
- InstantQueryResultBinderProvider(context)
- )
+ val queryResultBinderProviders: List<QueryResultBinderProvider> =
+ mutableListOf<QueryResultBinderProvider>().apply {
+ add(CursorQueryResultBinderProvider(context))
+ add(LiveDataQueryResultBinderProvider(context))
+ add(GuavaListenableFutureQueryResultBinderProvider(context))
+ addAll(RxQueryResultBinderProvider.getAll(context))
+ addAll(RxCallableQueryResultBinderProvider.getAll(context))
+ add(DataSourceQueryResultBinderProvider(context))
+ add(DataSourceFactoryQueryResultBinderProvider(context))
+ add(PagingSourceQueryResultBinderProvider(context))
+ add(CoroutineFlowResultBinderProvider(context))
+ add(InstantQueryResultBinderProvider(context))
+ }
- val preparedQueryResultBinderProviders = listOf(
- RxSinglePreparedQueryResultBinderProvider(context),
- RxMaybePreparedQueryResultBinderProvider(context),
- RxCompletablePreparedQueryResultBinderProvider(context),
- GuavaListenableFuturePreparedQueryResultBinderProvider(context),
- InstantPreparedQueryResultBinderProvider(context)
- )
+ val preparedQueryResultBinderProviders: List<PreparedQueryResultBinderProvider> =
+ mutableListOf<PreparedQueryResultBinderProvider>().apply {
+ addAll(RxPreparedQueryResultBinderProvider.getAll(context))
+ add(GuavaListenableFuturePreparedQueryResultBinderProvider(context))
+ add(InstantPreparedQueryResultBinderProvider(context))
+ }
- val insertBinderProviders = listOf(
- RxSingleInsertMethodBinderProvider(context),
- RxMaybeInsertMethodBinderProvider(context),
- RxCompletableInsertMethodBinderProvider(context),
- GuavaListenableFutureInsertMethodBinderProvider(context),
- InstantInsertMethodBinderProvider(context)
- )
+ val insertBinderProviders: List<InsertMethodBinderProvider> =
+ mutableListOf<InsertMethodBinderProvider>().apply {
+ addAll(RxCallableInsertMethodBinderProvider.getAll(context))
+ add(GuavaListenableFutureInsertMethodBinderProvider(context))
+ add(InstantInsertMethodBinderProvider(context))
+ }
- val deleteOrUpdateBinderProvider = listOf(
- RxSingleDeleteOrUpdateMethodBinderProvider(context),
- RxMaybeDeleteOrUpdateMethodBinderProvider(context),
- RxCompletableDeleteOrUpdateMethodBinderProvider(context),
- GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(context),
- InstantDeleteOrUpdateMethodBinderProvider(context)
- )
+ val deleteOrUpdateBinderProvider: List<DeleteOrUpdateMethodBinderProvider> =
+ mutableListOf<DeleteOrUpdateMethodBinderProvider>().apply {
+ addAll(RxCallableDeleteOrUpdateMethodBinderProvider.getAll(context))
+ add(GuavaListenableFutureDeleteOrUpdateMethodBinderProvider(context))
+ add(InstantDeleteOrUpdateMethodBinderProvider(context))
+ }
// type mirrors that be converted into columns w/o an extra converter
private val knownColumnTypeMirrors by lazy {
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
index 518500e..9cc4717 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
@@ -16,24 +16,22 @@
package androidx.room.solver.binderprovider
-import androidx.room.ext.RoomRxJava2TypeNames
import androidx.room.ext.typeName
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
-import androidx.room.processor.ProcessorErrors
import androidx.room.solver.QueryResultBinderProvider
+import androidx.room.solver.RxType
import androidx.room.solver.query.result.QueryResultBinder
import androidx.room.solver.query.result.RxCallableQueryResultBinder
import javax.lang.model.type.DeclaredType
-sealed class RxCallableQueryResultBinderProvider(
+class RxCallableQueryResultBinderProvider private constructor(
val context: Context,
- val rxType: RxCallableQueryResultBinder.RxType
-) :
- QueryResultBinderProvider {
- private val hasRxJava2Artifact by lazy {
+ private val rxType: RxType
+) : QueryResultBinderProvider {
+ private val hasRxJavaArtifact by lazy {
context.processingEnv.elementUtils
- .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
+ .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
}
override fun provide(declared: DeclaredType, query: ParsedQuery): QueryResultBinder {
@@ -43,20 +41,21 @@
}
override fun matches(declared: DeclaredType): Boolean =
- declared.typeArguments.size == 1 && matchesRxType(declared)
+ declared.typeArguments.size == 1 && matchesRxType(declared)
private fun matchesRxType(declared: DeclaredType): Boolean {
val erasure = context.processingEnv.typeUtils.erasure(declared)
val match = erasure.typeName() == rxType.className
- if (match && !hasRxJava2Artifact) {
- context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+ if (match && !hasRxJavaArtifact) {
+ context.logger.e(rxType.version.missingArtifactMessage)
}
return match
}
+
+ companion object {
+ fun getAll(context: Context) = listOf(
+ RxType.RX2_SINGLE,
+ RxType.RX2_MAYBE
+ ).map { RxCallableQueryResultBinderProvider(context, it) }
+ }
}
-
-class RxSingleQueryResultBinderProvider(context: Context) :
- RxCallableQueryResultBinderProvider(context, RxCallableQueryResultBinder.RxType.SINGLE)
-
-class RxMaybeQueryResultBinderProvider(context: Context) :
- RxCallableQueryResultBinderProvider(context, RxCallableQueryResultBinder.RxType.MAYBE)
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
index 67a9e87..7861ec7 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
@@ -16,27 +16,26 @@
package androidx.room.solver.binderprovider
-import androidx.room.ext.RoomRxJava2TypeNames
import androidx.room.processor.Context
-import androidx.room.processor.ProcessorErrors
import androidx.room.solver.ObservableQueryResultBinderProvider
+import androidx.room.solver.RxType
import androidx.room.solver.query.result.QueryResultAdapter
import androidx.room.solver.query.result.QueryResultBinder
import androidx.room.solver.query.result.RxQueryResultBinder
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
-sealed class RxQueryResultBinderProvider(
+class RxQueryResultBinderProvider private constructor(
context: Context,
- private val rxType: RxQueryResultBinder.RxType
+ private val rxType: RxType
) : ObservableQueryResultBinderProvider(context) {
private val typeMirror: TypeMirror? by lazy {
context.processingEnv.elementUtils
- .getTypeElement(rxType.className.toString())?.asType()
+ .getTypeElement(rxType.className.toString())?.asType()
}
- private val hasRxJava2Artifact by lazy {
+ private val hasRxJavaArtifact by lazy {
context.processingEnv.elementUtils
- .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
+ .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
}
override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
@@ -47,15 +46,15 @@
tableNames: Set<String>
): QueryResultBinder {
return RxQueryResultBinder(
- rxType = rxType,
- typeArg = typeArg,
- queryTableNames = tableNames,
- adapter = resultAdapter
+ rxType = rxType,
+ typeArg = typeArg,
+ queryTableNames = tableNames,
+ adapter = resultAdapter
)
}
override fun matches(declared: DeclaredType): Boolean =
- declared.typeArguments.size == 1 && matchesRxType(declared)
+ declared.typeArguments.size == 1 && matchesRxType(declared)
private fun matchesRxType(declared: DeclaredType): Boolean {
if (typeMirror == null) {
@@ -63,15 +62,16 @@
}
val erasure = context.processingEnv.typeUtils.erasure(declared)
val match = context.processingEnv.typeUtils.isAssignable(typeMirror, erasure)
- if (match && !hasRxJava2Artifact) {
- context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+ if (match && !hasRxJavaArtifact) {
+ context.logger.e(rxType.version.missingArtifactMessage)
}
return match
}
-}
-class RxFlowableQueryResultBinderProvider(context: Context) :
- RxQueryResultBinderProvider(context, RxQueryResultBinder.RxType.FLOWABLE)
-
-class RxObservableQueryResultBinderProvider(context: Context) :
- RxQueryResultBinderProvider(context, RxQueryResultBinder.RxType.OBSERVABLE)
\ No newline at end of file
+ companion object {
+ fun getAll(context: Context) = listOf(
+ RxType.RX2_FLOWABLE,
+ RxType.RX2_OBSERVABLE
+ ).map { RxQueryResultBinderProvider(context, it) }
+ }
+}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
index 6d12c62..57cef99 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
@@ -17,27 +17,25 @@
package androidx.room.solver.prepared.binderprovider
import androidx.room.ext.L
-import androidx.room.ext.RoomRxJava2TypeNames
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.T
import androidx.room.ext.typeName
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
-import androidx.room.processor.ProcessorErrors
+import androidx.room.solver.RxType
import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
-import com.squareup.javapoet.ClassName
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
-sealed class RxPreparedQueryResultBinderProvider(
+open class RxPreparedQueryResultBinderProvider internal constructor(
val context: Context,
- val rxType: RxType
+ private val rxType: RxType
) : PreparedQueryResultBinderProvider {
- private val hasRxJava2Artifact by lazy {
+ private val hasRxJavaArtifact by lazy {
context.processingEnv.elementUtils
- .getTypeElement(RoomRxJava2TypeNames.RX_ROOM.toString()) != null
+ .getTypeElement(rxType.version.rxRoomClassName.toString()) != null
}
override fun matches(declared: DeclaredType): Boolean =
@@ -49,8 +47,8 @@
}
override fun provide(declared: DeclaredType, query: ParsedQuery): PreparedQueryResultBinder {
- if (!hasRxJava2Artifact) {
- context.logger.e(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
+ if (!hasRxJavaArtifact) {
+ context.logger.e(rxType.version.missingArtifactMessage)
}
val typeArg = extractTypeArg(declared)
return createPreparedBinder(
@@ -61,27 +59,21 @@
}
}
- abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
+ open fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
- enum class RxType(val className: ClassName) {
- SINGLE(RxJava2TypeNames.SINGLE),
- MAYBE(RxJava2TypeNames.MAYBE),
- COMPLETABLE(RxJava2TypeNames.COMPLETABLE)
+ companion object {
+ fun getAll(context: Context) = listOf(
+ RxPreparedQueryResultBinderProvider(context, RxType.RX2_SINGLE),
+ RxPreparedQueryResultBinderProvider(context, RxType.RX2_MAYBE),
+ RxCompletablePreparedQueryResultBinderProvider(context, RxType.RX2_COMPLETABLE)
+ )
}
}
-class RxSinglePreparedQueryResultBinderProvider(context: Context) :
- RxPreparedQueryResultBinderProvider(context, RxType.SINGLE) {
- override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxMaybePreparedQueryResultBinderProvider(context: Context) :
- RxPreparedQueryResultBinderProvider(context, RxType.MAYBE) {
- override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxCompletablePreparedQueryResultBinderProvider(context: Context) :
- RxPreparedQueryResultBinderProvider(context, RxType.COMPLETABLE) {
+private class RxCompletablePreparedQueryResultBinderProvider(
+ context: Context,
+ rxType: RxType
+) : RxPreparedQueryResultBinderProvider(context, rxType) {
private val completableType: TypeMirror? by lazy {
context.processingEnv.elementUtils
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
index d42748a..d1eee32 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -17,17 +17,15 @@
package androidx.room.solver.query.result
import androidx.room.ext.AndroidTypeNames
+import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.L
import androidx.room.ext.N
-import androidx.room.ext.RoomRxJava2TypeNames
import androidx.room.ext.RoomTypeNames
-import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.S
import androidx.room.ext.T
-import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.typeName
import androidx.room.solver.CodeGenScope
-import com.squareup.javapoet.ClassName
+import androidx.room.solver.RxType
import com.squareup.javapoet.FieldSpec
import com.squareup.javapoet.MethodSpec
import javax.lang.model.element.Modifier
@@ -36,7 +34,7 @@
/**
* Generic Result binder for Rx classes that accept a callable.
*/
-class RxCallableQueryResultBinder(
+internal class RxCallableQueryResultBinder(
private val rxType: RxType,
val typeArg: TypeMirror,
adapter: QueryResultAdapter?
@@ -60,8 +58,8 @@
}
}.build()
scope.builder().apply {
- if (rxType == RxType.SINGLE) {
- addStatement("return $T.createSingle($L)", RoomRxJava2TypeNames.RX_ROOM, callable)
+ if (rxType.isSingle()) {
+ addStatement("return $T.createSingle($L)", rxType.version.rxRoomClassName, callable)
} else {
addStatement("return $T.fromCallable($L)", rxType.className, callable)
}
@@ -98,7 +96,7 @@
if (!rxType.canBeNull) {
beginControlFlow("if($L == null)", outVar).apply {
addStatement("throw new $T($S + $L.getSql())",
- RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+ rxType.version.emptyResultExceptionClassName,
"Query returned empty result set: ",
roomSQLiteQueryVar)
}
@@ -121,9 +119,4 @@
addStatement("$L.release()", roomSQLiteQueryVar)
}.build()
}
-
- enum class RxType(val className: ClassName, val canBeNull: Boolean) {
- SINGLE(RxJava2TypeNames.SINGLE, canBeNull = false),
- MAYBE(RxJava2TypeNames.MAYBE, canBeNull = true);
- }
}
\ No newline at end of file
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
index 4bdc734..109df19 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
@@ -16,23 +16,21 @@
package androidx.room.solver.query.result
+import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.L
import androidx.room.ext.N
-import androidx.room.ext.RoomRxJava2TypeNames
-import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.T
-import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.arrayTypeName
import androidx.room.ext.typeName
import androidx.room.solver.CodeGenScope
-import com.squareup.javapoet.ClassName
+import androidx.room.solver.RxType
import com.squareup.javapoet.FieldSpec
import javax.lang.model.type.TypeMirror
/**
* Binds the result as an RxJava2 Flowable, Publisher and Observable.
*/
-class RxQueryResultBinder(
+internal class RxQueryResultBinder(
private val rxType: RxType,
val typeArg: TypeMirror,
val queryTableNames: Set<String>,
@@ -60,8 +58,8 @@
scope.builder().apply {
val tableNamesList = queryTableNames.joinToString(",") { "\"$it\"" }
addStatement("return $T.$N($N, $L, new $T{$L}, $L)",
- RoomRxJava2TypeNames.RX_ROOM,
- rxType.methodName,
+ rxType.version.rxRoomClassName,
+ rxType.factoryMethodName,
dbField,
if (inTransaction) "true" else "false",
String::class.arrayTypeName(),
@@ -69,9 +67,4 @@
callableImpl)
}
}
-
- enum class RxType(val className: ClassName, val methodName: String) {
- FLOWABLE(RxJava2TypeNames.FLOWABLE, RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE),
- OBSERVABLE(RxJava2TypeNames.OBSERVABLE, RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE)
- }
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
index 0f04bda..67bb1f8 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
@@ -21,16 +21,16 @@
import androidx.room.ext.T
import androidx.room.ext.typeName
import androidx.room.processor.Context
+import androidx.room.solver.RxType
import androidx.room.solver.shortcut.binder.CallableDeleteOrUpdateMethodBinder.Companion.createDeleteOrUpdateBinder
import androidx.room.solver.shortcut.binder.DeleteOrUpdateMethodBinder
-import com.squareup.javapoet.ClassName
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
/**
* Provider for Rx Callable binders.
*/
-sealed class RxCallableDeleteOrUpdateMethodBinderProvider(
+open class RxCallableDeleteOrUpdateMethodBinderProvider internal constructor(
val context: Context,
private val rxType: RxType
) : DeleteOrUpdateMethodBinderProvider {
@@ -39,7 +39,7 @@
* [Single] and [Maybe] are generics but [Completable] is not so each implementation of this
* class needs to define how to extract the type argument.
*/
- abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
+ open fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
override fun matches(declared: DeclaredType): Boolean =
declared.typeArguments.size == 1 && matchesRxType(declared)
@@ -57,30 +57,19 @@
}
}
- /**
- * Supported types for delete and update
- */
- enum class RxType(val className: ClassName) {
- SINGLE(RxJava2TypeNames.SINGLE),
- MAYBE(RxJava2TypeNames.MAYBE),
- COMPLETABLE(RxJava2TypeNames.COMPLETABLE)
+ companion object {
+ fun getAll(context: Context) = listOf(
+ RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.RX2_SINGLE),
+ RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.RX2_MAYBE),
+ RxCompletableDeleteOrUpdateMethodBinderProvider(context, RxType.RX2_COMPLETABLE)
+ )
}
}
-class RxSingleDeleteOrUpdateMethodBinderProvider(context: Context) :
- RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.SINGLE) {
-
- override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxMaybeDeleteOrUpdateMethodBinderProvider(context: Context) :
- RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.MAYBE) {
-
- override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxCompletableDeleteOrUpdateMethodBinderProvider(context: Context) :
- RxCallableDeleteOrUpdateMethodBinderProvider(context, RxType.COMPLETABLE) {
+private class RxCompletableDeleteOrUpdateMethodBinderProvider(
+ context: Context,
+ rxType: RxType
+) : RxCallableDeleteOrUpdateMethodBinderProvider(context, rxType) {
private val completableTypeMirror: TypeMirror? by lazy {
context.processingEnv.elementUtils
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
index c207d18..14c2ead 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertMethodBinderProvider.kt
@@ -17,21 +17,20 @@
package androidx.room.solver.shortcut.binderprovider
import androidx.room.ext.L
-import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.T
import androidx.room.ext.typeName
import androidx.room.processor.Context
+import androidx.room.solver.RxType
import androidx.room.solver.shortcut.binder.CallableInsertMethodBinder.Companion.createInsertBinder
import androidx.room.solver.shortcut.binder.InsertMethodBinder
import androidx.room.vo.ShortcutQueryParameter
-import com.squareup.javapoet.ClassName
import javax.lang.model.type.DeclaredType
import javax.lang.model.type.TypeMirror
/**
* Provider for Rx Callable binders.
*/
-sealed class RxCallableInsertMethodBinderProvider(
+open class RxCallableInsertMethodBinderProvider internal constructor(
val context: Context,
private val rxType: RxType
) : InsertMethodBinderProvider {
@@ -40,7 +39,7 @@
* [Single] and [Maybe] are generics but [Completable] is not so each implementation of this
* class needs to define how to extract the type argument.
*/
- abstract fun extractTypeArg(declared: DeclaredType): TypeMirror
+ open fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
override fun matches(declared: DeclaredType): Boolean =
declared.typeArguments.size == 1 && matchesRxType(declared)
@@ -61,35 +60,23 @@
}
}
- /**
- * Supported types for insert
- */
- enum class RxType(val className: ClassName) {
- SINGLE(RxJava2TypeNames.SINGLE),
- MAYBE(RxJava2TypeNames.MAYBE),
- COMPLETABLE(RxJava2TypeNames.COMPLETABLE)
+ companion object {
+ fun getAll(context: Context) = listOf(
+ RxCallableInsertMethodBinderProvider(context, RxType.RX2_SINGLE),
+ RxCallableInsertMethodBinderProvider(context, RxType.RX2_MAYBE),
+ RxCompletableInsertMethodBinderProvider(context, RxType.RX2_COMPLETABLE)
+ )
}
}
-class RxSingleInsertMethodBinderProvider(context: Context) :
- RxCallableInsertMethodBinderProvider(context, RxType.SINGLE) {
-
- override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxMaybeInsertMethodBinderProvider(context: Context) :
- RxCallableInsertMethodBinderProvider(context, RxType.MAYBE) {
-
- override fun extractTypeArg(declared: DeclaredType): TypeMirror = declared.typeArguments.first()
-}
-
-class RxCompletableInsertMethodBinderProvider(context: Context) :
- RxCallableInsertMethodBinderProvider(context,
- RxType.COMPLETABLE) {
+private class RxCompletableInsertMethodBinderProvider(
+ context: Context,
+ rxType: RxType
+) : RxCallableInsertMethodBinderProvider(context, rxType) {
private val completableTypeMirror: TypeMirror? by lazy {
context.processingEnv.elementUtils
- .getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())?.asType()
+ .getTypeElement(rxType.className.toString())?.asType()
}
/**
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index ce30049..6c79762 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -36,16 +36,11 @@
import androidx.room.solver.binderprovider.DataSourceQueryResultBinderProvider
import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxFlowableQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxObservableQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureDeleteOrUpdateMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxCompletableInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxMaybeInsertMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleDeleteOrUpdateMethodBinderProvider
-import androidx.room.solver.shortcut.binderprovider.RxSingleInsertMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableDeleteOrUpdateMethodBinderProvider
+import androidx.room.solver.shortcut.binderprovider.RxCallableInsertMethodBinderProvider
import androidx.room.solver.types.CompositeAdapter
import androidx.room.solver.types.TypeConverter
import androidx.room.testing.TestInvocation
@@ -242,8 +237,10 @@
val publisherElement = invocation.processingEnv.elementUtils
.getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
assertThat(publisherElement, notNullValue())
- assertThat(RxFlowableQueryResultBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(publisherElement.asType())), `is`(true))
+ assertThat(
+ RxQueryResultBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(publisherElement.asType()))
+ }, `is`(true))
}.failsToCompile().withErrorContaining(ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT)
}
@@ -254,8 +251,10 @@
val publisher = invocation.processingEnv.elementUtils
.getTypeElement(ReactiveStreamsTypeNames.PUBLISHER.toString())
assertThat(publisher, notNullValue())
- assertThat(RxFlowableQueryResultBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(publisher.asType())), `is`(true))
+ assertThat(
+ RxQueryResultBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(publisher.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -266,8 +265,10 @@
val flowable = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.FLOWABLE.toString())
assertThat(flowable, notNullValue())
- assertThat(RxFlowableQueryResultBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(flowable.asType())), `is`(true))
+ assertThat(
+ RxQueryResultBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(flowable.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -278,8 +279,10 @@
val observable = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.OBSERVABLE.toString())
assertThat(observable, notNullValue())
- assertThat(RxObservableQueryResultBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(observable.asType())), `is`(true))
+ assertThat(
+ RxQueryResultBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(observable.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -290,8 +293,10 @@
val single = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.SINGLE.toString())
assertThat(single, notNullValue())
- assertThat(RxSingleInsertMethodBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(single.asType())), `is`(true))
+ assertThat(
+ RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(single.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -302,8 +307,10 @@
val maybe = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.MAYBE.toString())
assertThat(maybe, notNullValue())
- assertThat(RxMaybeInsertMethodBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(maybe.asType())), `is`(true))
+ assertThat(
+ RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(maybe.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -314,8 +321,10 @@
val completable = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())
assertThat(completable, notNullValue())
- assertThat(RxCompletableInsertMethodBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(completable.asType())), `is`(true))
+ assertThat(
+ RxCallableInsertMethodBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(completable.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -338,8 +347,10 @@
val single = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.SINGLE.toString())
assertThat(single, notNullValue())
- assertThat(RxSingleDeleteOrUpdateMethodBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(single.asType())), `is`(true))
+ assertThat(
+ RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(single.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -350,8 +361,10 @@
val maybe = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.MAYBE.toString())
assertThat(maybe, notNullValue())
- assertThat(RxMaybeDeleteOrUpdateMethodBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(maybe.asType())), `is`(true))
+ assertThat(
+ RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(maybe.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
@@ -362,8 +375,10 @@
val completable = invocation.processingEnv.elementUtils
.getTypeElement(RxJava2TypeNames.COMPLETABLE.toString())
assertThat(completable, notNullValue())
- assertThat(RxCompletableDeleteOrUpdateMethodBinderProvider(invocation.context).matches(
- MoreTypes.asDeclared(completable.asType())), `is`(true))
+ assertThat(
+ RxCallableDeleteOrUpdateMethodBinderProvider.getAll(invocation.context).any {
+ it.matches(MoreTypes.asDeclared(completable.asType()))
+ }, `is`(true))
}.compilesWithoutError()
}
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index f1cac00..a664d56 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -97,6 +97,7 @@
androidTestImplementation(projectOrArtifact(":paging:paging-runtime"))
androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime"))
androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime-testing"))
+ androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-livedata"))
// FINDBUGS dependency resolves an app/testapp version conflict.
androidTestImplementation(FINDBUGS)
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
index de24eaa..b46e492 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
@@ -25,7 +25,6 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
-import android.content.Intent;
import android.os.Build;
import android.os.SystemClock;
@@ -57,6 +56,7 @@
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import java.util.ArrayList;
@@ -72,6 +72,9 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
public class MultiInstanceInvalidationTest {
+ @Rule
+ public TestName testName = new TestName();
+
private static final Customer CUSTOMER_1 = new Customer();
private static final Customer CUSTOMER_2 = new Customer();
@@ -89,6 +92,8 @@
private ISampleDatabaseService mService;
+ private String mDatabaseName;
+
private final ArrayList<RoomDatabase> mDatabases = new ArrayList<>();
private final SimpleArrayMap<LiveData<List<Customer>>, Observer<List<Customer>>> mObservers =
new SimpleArrayMap<>();
@@ -96,7 +101,10 @@
@Before
public void setUp() {
final Context context = ApplicationProvider.getApplicationContext();
- context.deleteDatabase(SampleDatabaseService.DATABASE_NAME);
+ // use a separate database file for each test because we are not fully capable of closing
+ // and deleting a database connection in a multi-process setup
+ mDatabaseName = "multi-process-" + testName.getMethodName() + ".db";
+ context.deleteDatabase(mDatabaseName);
}
@After
@@ -339,7 +347,7 @@
private long measure(boolean multiInstanceInvalidation, boolean bulk,
List<Customer> customers) {
final Context context = ApplicationProvider.getApplicationContext();
- context.deleteDatabase(SampleDatabaseService.DATABASE_NAME);
+ context.deleteDatabase(mDatabaseName);
final SampleDatabase db = openDatabase(multiInstanceInvalidation);
final CustomerDao dao = db.getCustomerDao();
final InvalidationTracker.Observer observer = new InvalidationTracker.Observer("Customer") {
@@ -373,8 +381,7 @@
private SampleDatabase openDatabase(boolean multiInstanceInvalidation) {
final Context context = ApplicationProvider.getApplicationContext();
final RoomDatabase.Builder<SampleDatabase> builder = Room
- .databaseBuilder(context, SampleDatabase.class,
- SampleDatabaseService.DATABASE_NAME);
+ .databaseBuilder(context, SampleDatabase.class, mDatabaseName);
if (multiInstanceInvalidation) {
builder.enableMultiInstanceInvalidation();
}
@@ -386,8 +393,7 @@
private SampleFtsDatabase openFtsDatabase(boolean multiInstanceInvalidation) {
final Context context = ApplicationProvider.getApplicationContext();
final RoomDatabase.Builder<SampleFtsDatabase> builder = Room
- .databaseBuilder(context, SampleFtsDatabase.class,
- SampleDatabaseService.DATABASE_NAME);
+ .databaseBuilder(context, SampleFtsDatabase.class, mDatabaseName);
if (multiInstanceInvalidation) {
builder.enableMultiInstanceInvalidation();
}
@@ -399,7 +405,10 @@
private void bindTestService() throws TimeoutException {
final Context context = ApplicationProvider.getApplicationContext();
mService = ISampleDatabaseService.Stub.asInterface(
- serviceRule.bindService(new Intent(context, SampleDatabaseService.class)));
+ serviceRule.bindService(SampleDatabaseService.intentFor(
+ context,
+ mDatabaseName
+ )));
}
private CountDownLatch prepareTableObserver(SampleDatabase db) {
diff --git a/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java b/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java
index 8df5ecd..baafa36 100644
--- a/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java
+++ b/room/integration-tests/testapp/src/main/java/androidx/room/integration/testapp/SampleDatabaseService.java
@@ -17,6 +17,7 @@
package androidx.room.integration.testapp;
import android.app.Service;
+import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
@@ -39,7 +40,7 @@
*/
public class SampleDatabaseService extends Service {
- public static final String DATABASE_NAME = "multi-process.db";
+ private static final String DATABASE_NAME_PARAM = "db-name";
private final ISampleDatabaseService.Stub mBinder = new ISampleDatabaseService.Stub() {
@@ -87,14 +88,39 @@
@Override
public void onCreate() {
super.onCreate();
- mDatabase = Room.databaseBuilder(this, SampleDatabase.class, DATABASE_NAME)
- .enableMultiInstanceInvalidation()
- .build();
+ }
+
+ /**
+ * Creates the test service for the given database name
+ * @param context The context to creat the intent
+ * @param databaseName The database name to be used
+ * @return A new intent that can be used to connect to this service
+ */
+ public static Intent intentFor(Context context, String databaseName) {
+ Intent intent = new Intent(context, SampleDatabaseService.class);
+ intent.putExtra(DATABASE_NAME_PARAM, databaseName);
+ return intent;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
+ String databaseName = intent.getStringExtra(DATABASE_NAME_PARAM);
+ if (databaseName == null) {
+ throw new IllegalArgumentException("must pass database name in the intent");
+ }
+ if (mDatabase != null) {
+ throw new IllegalStateException("Cannot re-use the same service for different tests");
+ }
+ mDatabase = Room.databaseBuilder(this, SampleDatabase.class, databaseName)
+ .enableMultiInstanceInvalidation()
+ .build();
return mBinder;
}
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ mDatabase.close();
+ return super.onUnbind(intent);
+ }
}
diff --git a/room/ktx/api/restricted_2.3.0-alpha02.txt b/room/ktx/api/restricted_2.3.0-alpha02.txt
index cc27399..371c63c 100644
--- a/room/ktx/api/restricted_2.3.0-alpha02.txt
+++ b/room/ktx/api/restricted_2.3.0-alpha02.txt
@@ -5,7 +5,7 @@
method public static <R> kotlinx.coroutines.flow.Flow<R> createFlow(androidx.room.RoomDatabase db, boolean inTransaction, String![] tableNames, java.util.concurrent.Callable<R> callable);
method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, java.util.concurrent.Callable<R> inTransaction, kotlin.coroutines.Continuation<? super R> callable);
method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, android.os.CancellationSignal inTransaction, java.util.concurrent.Callable<R> cancellationSignal, kotlin.coroutines.Continuation<? super R> callable);
- field public static final androidx.room.CoroutinesRoom.Companion! Companion;
+ field public static final androidx.room.CoroutinesRoom.Companion Companion;
}
public static final class CoroutinesRoom.Companion {
diff --git a/room/ktx/api/restricted_current.txt b/room/ktx/api/restricted_current.txt
index cc27399..371c63c 100644
--- a/room/ktx/api/restricted_current.txt
+++ b/room/ktx/api/restricted_current.txt
@@ -5,7 +5,7 @@
method public static <R> kotlinx.coroutines.flow.Flow<R> createFlow(androidx.room.RoomDatabase db, boolean inTransaction, String![] tableNames, java.util.concurrent.Callable<R> callable);
method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, java.util.concurrent.Callable<R> inTransaction, kotlin.coroutines.Continuation<? super R> callable);
method public static suspend <R> Object? execute(androidx.room.RoomDatabase p, boolean db, android.os.CancellationSignal inTransaction, java.util.concurrent.Callable<R> cancellationSignal, kotlin.coroutines.Continuation<? super R> callable);
- field public static final androidx.room.CoroutinesRoom.Companion! Companion;
+ field public static final androidx.room.CoroutinesRoom.Companion Companion;
}
public static final class CoroutinesRoom.Companion {
diff --git a/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java b/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java
index 3dbb8e0..c8a7b5d 100644
--- a/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java
+++ b/room/runtime/src/main/java/androidx/room/MultiInstanceInvalidationClient.java
@@ -138,22 +138,6 @@
}
};
- private final Runnable mTearDownRunnable = new Runnable() {
- @Override
- public void run() {
- mInvalidationTracker.removeObserver(mObserver);
- try {
- final IMultiInstanceInvalidationService service = mService;
- if (service != null) {
- service.unregisterCallback(mCallback, mClientId);
- }
- } catch (RemoteException e) {
- Log.w(Room.LOG_TAG, "Cannot unregister multi-instance invalidation callback", e);
- }
- mAppContext.unbindService(mServiceConnection);
- }
- };
-
/**
* @param context The Context to be used for binding
* {@link IMultiInstanceInvalidationService}.
@@ -196,7 +180,16 @@
void stop() {
if (mStopped.compareAndSet(false, true)) {
- mExecutor.execute(mTearDownRunnable);
+ mInvalidationTracker.removeObserver(mObserver);
+ try {
+ final IMultiInstanceInvalidationService service = mService;
+ if (service != null) {
+ service.unregisterCallback(mCallback, mClientId);
+ }
+ } catch (RemoteException e) {
+ Log.w(Room.LOG_TAG, "Cannot unregister multi-instance invalidation callback", e);
+ }
+ mAppContext.unbindService(mServiceConnection);
}
}
}
diff --git a/samples/Support7Demos/OWNERS b/samples/Support7Demos/OWNERS
index 2f5d227..526fcca 100644
--- a/samples/Support7Demos/OWNERS
+++ b/samples/Support7Demos/OWNERS
@@ -1,6 +1,7 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
\ No newline at end of file
[email protected]
[email protected]
[email protected]
diff --git a/security/crypto/api/api_lint.ignore b/security/crypto/api/api_lint.ignore
index b3ea816..0b681f2 100644
--- a/security/crypto/api/api_lint.ignore
+++ b/security/crypto/api/api_lint.ignore
@@ -9,7 +9,3 @@
Listener methods should be named add/remove; was registerOnSharedPreferenceChangeListener
RegistrationName: androidx.security.crypto.EncryptedSharedPreferences#unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener):
Listener methods should be named add/remove; was unregisterOnSharedPreferenceChangeListener
-
-
-StreamFiles: androidx.security.crypto.EncryptedFile.Builder#Builder(java.io.File, android.content.Context, String, androidx.security.crypto.EncryptedFile.FileEncryptionScheme):
- Methods accepting `File` should also accept `FileDescriptor` or streams: constructor androidx.security.crypto.EncryptedFile.Builder(java.io.File,android.content.Context,String,androidx.security.crypto.EncryptedFile.FileEncryptionScheme)
diff --git a/serialization/serialization-annotation/api/1.0.0-alpha01.txt b/serialization/serialization-annotation/api/1.0.0-alpha01.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/1.0.0-alpha01.txt
+++ b/serialization/serialization-annotation/api/1.0.0-alpha01.txt
@@ -23,6 +23,8 @@
}
public enum ProtoEncoding {
+ method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.serialization.ProtoEncoding[] values();
enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/current.txt b/serialization/serialization-annotation/api/current.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/current.txt
+++ b/serialization/serialization-annotation/api/current.txt
@@ -23,6 +23,8 @@
}
public enum ProtoEncoding {
+ method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.serialization.ProtoEncoding[] values();
enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt b/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt
+++ b/serialization/serialization-annotation/api/public_plus_experimental_1.0.0-alpha01.txt
@@ -23,6 +23,8 @@
}
public enum ProtoEncoding {
+ method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.serialization.ProtoEncoding[] values();
enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/public_plus_experimental_current.txt b/serialization/serialization-annotation/api/public_plus_experimental_current.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/public_plus_experimental_current.txt
+++ b/serialization/serialization-annotation/api/public_plus_experimental_current.txt
@@ -23,6 +23,8 @@
}
public enum ProtoEncoding {
+ method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.serialization.ProtoEncoding[] values();
enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt b/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt
+++ b/serialization/serialization-annotation/api/restricted_1.0.0-alpha01.txt
@@ -23,6 +23,8 @@
}
public enum ProtoEncoding {
+ method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.serialization.ProtoEncoding[] values();
enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/serialization/serialization-annotation/api/restricted_current.txt b/serialization/serialization-annotation/api/restricted_current.txt
index e3f604ac..5570701 100644
--- a/serialization/serialization-annotation/api/restricted_current.txt
+++ b/serialization/serialization-annotation/api/restricted_current.txt
@@ -23,6 +23,8 @@
}
public enum ProtoEncoding {
+ method public static androidx.serialization.ProtoEncoding valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.serialization.ProtoEncoding[] values();
enum_constant public static final androidx.serialization.ProtoEncoding DEFAULT;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_FIXED;
enum_constant public static final androidx.serialization.ProtoEncoding SIGNED_VARINT;
diff --git a/slices/benchmark/src/androidTest/AndroidManifest.xml b/slices/benchmark/src/androidTest/AndroidManifest.xml
index 5fd3108..8e2298b 100644
--- a/slices/benchmark/src/androidTest/AndroidManifest.xml
+++ b/slices/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,5 +23,8 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java b/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java
index 4ab5626..2e1323e 100644
--- a/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java
+++ b/slices/view/src/main/java/androidx/slice/SliceViewManagerBase.java
@@ -87,10 +87,10 @@
private class SliceListenerImpl {
- Uri mUri;
+ final Uri mUri;
final Executor mExecutor;
final SliceCallback mCallback;
- private boolean mPinned;
+ boolean mPinned;
SliceListenerImpl(Uri uri, Executor executor, SliceCallback callback) {
mUri = uri;
@@ -119,14 +119,24 @@
}
}
+ @SuppressWarnings("deprecation") /* AsyncTask */
void stopListening() {
mContext.getContentResolver().unregisterContentObserver(mObserver);
if (mPinned) {
- unpinSlice(mUri);
- mPinned = false;
+ mHandler.post(() -> android.os.AsyncTask.execute(mUnpinSlice));
}
}
+ private final Runnable mUnpinSlice = new Runnable() {
+ @Override
+ public void run() {
+ if (mPinned) {
+ unpinSlice(mUri);
+ mPinned = false;
+ }
+ }
+ };
+
final Runnable mUpdateSlice = new Runnable() {
@Override
public void run() {
@@ -141,8 +151,9 @@
}
};
- private final ContentObserver mObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+ private final ContentObserver mObserver = new ContentObserver(mHandler) {
@Override
@SuppressWarnings("deprecation") /* AsyncTask */
public void onChange(boolean selfChange) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowStyle.java b/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
index 8bd56f8..05055df 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowStyle.java
@@ -50,6 +50,8 @@
private int mProgressBarStartPadding;
private int mProgressBarEndPadding;
private int mIconSize;
+ private boolean mDisableRecyclerViewItemAnimator;
+ private int mImageSize;
public RowStyle(Context context, int resId) {
TypedArray a = context.getTheme().obtainStyledAttributes(resId, R.styleable.RowStyle);
@@ -90,6 +92,10 @@
R.styleable.RowStyle_progressBarEndPadding, UNBOUNDED);
mIconSize = (int) a.getDimension(
R.styleable.RowStyle_iconSize, UNBOUNDED);
+ mDisableRecyclerViewItemAnimator = a.getBoolean(
+ R.styleable.RowStyle_disableRecyclerViewItemAnimator, false);
+ mImageSize = (int) a.getDimension(
+ R.styleable.RowStyle_imageSize, UNBOUNDED);
} finally {
a.recycle();
}
@@ -166,4 +172,12 @@
public int getIconSize() {
return mIconSize;
}
+
+ public boolean getDisableRecyclerViewItemAnimator() {
+ return mDisableRecyclerViewItemAnimator;
+ }
+
+ public int getImageSize() {
+ return mImageSize;
+ }
}
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowView.java b/slices/view/src/main/java/androidx/slice/widget/RowView.java
index 5e4a0b2..be3932d 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowView.java
@@ -105,6 +105,8 @@
private static final String TAG = "RowView";
+ private static final int HEIGHT_UNBOUND = -1;
+
// The number of items that fit on the right hand side of a small slice
// TODO: this should be based on available width
private static final int MAX_END_ITEMS = 3;
@@ -176,6 +178,7 @@
private int mImageSize;
private int mIconSize;
+ private int mStyleRowHeight = HEIGHT_UNBOUND;
// How big mRangeBar wants to be.
private int mMeasuredRangeHeight;
@@ -848,7 +851,7 @@
*/
private void addAction(final SliceActionImpl actionContent, int color, ViewGroup container,
boolean isStart) {
- SliceActionView sav = new SliceActionView(getContext());
+ SliceActionView sav = new SliceActionView(getContext(), mSliceStyle);
container.addView(sav);
if (container.getVisibility() == GONE) {
container.setVisibility(VISIBLE);
@@ -916,16 +919,25 @@
} else {
container.addView(iv);
}
+ if (mSliceStyle != null) {
+ mStyleRowHeight = mSliceStyle.getRowMinHeight();
+ if (mSliceStyle.getRowStyle() != null) {
+ int styleIconSize = mSliceStyle.getRowStyle().getIconSize();
+ mIconSize = styleIconSize > 0 ? styleIconSize : mIconSize;
+ int styleImageSize = mSliceStyle.getRowStyle().getImageSize();
+ mImageSize = styleImageSize > 0 ? styleImageSize : mImageSize;
+ }
+ }
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) iv.getLayoutParams();
lp.width = useIntrinsicSize ? Math.round(d.getIntrinsicWidth() / density) : mImageSize;
lp.height = useIntrinsicSize ? Math.round(d.getIntrinsicHeight() / density) :
mImageSize;
iv.setLayoutParams(lp);
- if (mSliceStyle != null && mSliceStyle.getRowStyle() != null) {
- int styleIconSize = mSliceStyle.getRowStyle().getIconSize();
- mIconSize = styleIconSize > 0 ? styleIconSize : mIconSize;
+ int p = 0;
+ if (isIcon) {
+ p = mStyleRowHeight == HEIGHT_UNBOUND
+ ? mIconSize / 2 : (mStyleRowHeight - mIconSize) / 2;
}
- int p = isIcon ? mIconSize / 2 : 0;
iv.setPadding(p, p, p, p);
addedView = iv;
} else if (timeStamp != null) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java b/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java
index 011a129..b2700f5 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceActionView.java
@@ -58,6 +58,8 @@
CompoundButton.OnCheckedChangeListener {
private static final String TAG = "SliceActionView";
+ private static final int HEIGHT_UNBOUND = -1;
+
static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
@@ -76,12 +78,20 @@
private int mIconSize;
private int mImageSize;
+ private int mStyleRowHeight = HEIGHT_UNBOUND;
- public SliceActionView(Context context) {
+ public SliceActionView(Context context, SliceStyle style) {
super(context);
Resources res = getContext().getResources();
mIconSize = res.getDimensionPixelSize(R.dimen.abc_slice_icon_size);
mImageSize = res.getDimensionPixelSize(R.dimen.abc_slice_small_image_size);
+ if (style != null) {
+ mStyleRowHeight = style.getRowMinHeight();
+ if (style.getRowStyle() != null) {
+ mIconSize = style.getRowStyle().getIconSize();
+ mImageSize = style.getRowStyle().getImageSize();
+ }
+ }
}
/**
@@ -164,7 +174,11 @@
lp.width = mImageSize;
lp.height = mImageSize;
mActionView.setLayoutParams(lp);
- int p = action.getImageMode() == ICON_IMAGE ? mIconSize / 2 : 0;
+ int p = 0;
+ if (action.getImageMode() == ICON_IMAGE) {
+ p = mStyleRowHeight == HEIGHT_UNBOUND
+ ? mIconSize / 2 : (mStyleRowHeight - mIconSize) / 2;
+ }
mActionView.setPadding(p, p, p, p);
int touchFeedbackAttr = android.R.attr.selectableItemBackground;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -224,7 +238,7 @@
}
@Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ public void onCheckedChanged(@Nullable CompoundButton buttonView, boolean isChecked) {
if (mSliceAction == null || mActionView == null) {
return;
}
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java b/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java
index 74dd01d..5b41309 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceStyle.java
@@ -117,6 +117,11 @@
mRowStyle = new RowStyle(context, rowStyleRes);
}
+ int defaultRowMinHeight = context.getResources().getDimensionPixelSize(
+ R.dimen.abc_slice_row_min_height);
+ mRowMinHeight = (int) a.getDimension(
+ R.styleable.SliceView_rowMinHeight, defaultRowMinHeight);
+
int defaultRowMaxHeight = context.getResources().getDimensionPixelSize(
R.dimen.abc_slice_row_max_height);
mRowMaxHeight = (int) a.getDimension(
@@ -142,7 +147,6 @@
mRowTextWithRangeHeight = r.getDimensionPixelSize(
R.dimen.abc_slice_row_range_multi_text_height);
- mRowMinHeight = r.getDimensionPixelSize(R.dimen.abc_slice_row_min_height);
mRowSelectionHeight = r.getDimensionPixelSize(R.dimen.abc_slice_row_selection_height);
mRowTextWithSelectionHeight = r.getDimensionPixelSize(
R.dimen.abc_slice_row_selection_multi_text_height);
@@ -161,6 +165,10 @@
mListLargeHeight = r.getDimensionPixelSize(R.dimen.abc_slice_large_height);
}
+ public int getRowMinHeight() {
+ return mRowMinHeight;
+ }
+
public int getRowMaxHeight() {
return mRowMaxHeight;
}
diff --git a/slices/view/src/main/java/androidx/slice/widget/TemplateView.java b/slices/view/src/main/java/androidx/slice/widget/TemplateView.java
index a331ec1..02cc488 100644
--- a/slices/view/src/main/java/androidx/slice/widget/TemplateView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/TemplateView.java
@@ -170,6 +170,18 @@
public void setStyle(SliceStyle style) {
super.setStyle(style);
mAdapter.setStyle(style);
+ applyRowStyle();
+ }
+
+ private void applyRowStyle() {
+ if (mSliceStyle == null || mSliceStyle.getRowStyle() == null) {
+ return;
+ }
+
+ final RowStyle rowStyle = mSliceStyle.getRowStyle();
+ if (rowStyle.getDisableRecyclerViewItemAnimator()) {
+ mRecyclerView.setItemAnimator(null);
+ }
}
@Override
diff --git a/slices/view/src/main/res-public/values/public_attrs.xml b/slices/view/src/main/res-public/values/public_attrs.xml
index 0442c73..fdfebd8 100644
--- a/slices/view/src/main/res-public/values/public_attrs.xml
+++ b/slices/view/src/main/res-public/values/public_attrs.xml
@@ -46,6 +46,7 @@
<public type="attr" name="bottomDividerStartPadding" />
<public type="attr" name="bottomDividerEndPadding" />
<public type="attr" name="actionDividerHeight" />
+ <public type="attr" name="rowMinHeight" />
<public type="attr" name="rowMaxHeight" />
<public type="attr" name="rowRangeHeight" />
<public type="attr" name="rowRangeSingleTextHeight" />
@@ -54,4 +55,6 @@
<public type="attr" name="progressBarStartPadding" />
<public type="attr" name="progressBarEndPadding" />
<public type="attr" name="iconSize" />
+ <public type="attr" name="imageSize" />
+ <public type="attr" name="disableRecyclerViewItemAnimator" />
</resources>
diff --git a/slices/view/src/main/res/values/attrs.xml b/slices/view/src/main/res/values/attrs.xml
index 8c16813..b0e64ce 100644
--- a/slices/view/src/main/res/values/attrs.xml
+++ b/slices/view/src/main/res/values/attrs.xml
@@ -59,6 +59,8 @@
may set this in your app theme pointing to your custom RowView style.-->
<attr name="rowStyle" format="reference" />
+ <!-- Min height of row view; default size if one line of text -->
+ <attr name="rowMinHeight" format="dimension" />
<!-- Size of row view with two lines of text -->
<attr name="rowMaxHeight" format="dimension" />
<!-- Size of range area in a row to fit a slider or progress bar -->
@@ -117,5 +119,10 @@
<!-- Size of icon. -->
<attr name="iconSize" format="dimension" />
+ <!-- Size of small images in a slice. -->
+ <attr name="imageSize" format="dimension" />
+ <!-- Control whether RecyclerView item animator is disable or not, true for disable
+ otherwise enable. -->
+ <attr name="disableRecyclerViewItemAnimator" format="boolean" />
</declare-styleable>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/startup/startup-runtime/build.gradle b/startup/startup-runtime/build.gradle
index aeb135f..ef99fb7 100644
--- a/startup/startup-runtime/build.gradle
+++ b/startup/startup-runtime/build.gradle
@@ -28,6 +28,9 @@
}
android {
+ buildTypes.all {
+ consumerProguardFiles 'proguard-rules.pro'
+ }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
diff --git a/startup/startup-runtime/proguard-rules.pro b/startup/startup-runtime/proguard-rules.pro
index f55c09a..b1048d8 100644
--- a/startup/startup-runtime/proguard-rules.pro
+++ b/startup/startup-runtime/proguard-rules.pro
@@ -2,7 +2,7 @@
# This is because they are discovered and instantiated during application initialization.
-keep class * extends androidx.startup.Initializer {
# Keep the public no-argument constructor while allowing other methods to be optimized.
- public <init>();
+ <init>();
}
-assumenosideeffects class androidx.startup.StartupLogger
diff --git a/textclassifier/textclassifier/api/1.0.0-alpha03.txt b/textclassifier/textclassifier/api/1.0.0-alpha03.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/1.0.0-alpha03.txt
+++ b/textclassifier/textclassifier/api/1.0.0-alpha03.txt
@@ -271,7 +271,7 @@
}
public final class TextLinksParams {
- field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+ field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
}
public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/api_lint.ignore b/textclassifier/textclassifier/api/api_lint.ignore
index b4fcb1d..aec5e8c 100644
--- a/textclassifier/textclassifier/api/api_lint.ignore
+++ b/textclassifier/textclassifier/api/api_lint.ignore
@@ -47,7 +47,5 @@
Missing nullability on method `createSpan` return
MissingNullability: androidx.textclassifier.TextLinks.TextLink#getConfidenceScore(String) parameter #0:
Missing nullability on parameter `entityType` in method `getConfidenceScore`
-MissingNullability: androidx.textclassifier.TextLinksParams#DEFAULT_PARAMS:
- Missing nullability on field `DEFAULT_PARAMS` in class `class androidx.textclassifier.TextLinksParams`
MissingNullability: androidx.textclassifier.TextSelection#getConfidenceScore(String) parameter #0:
Missing nullability on parameter `entity` in method `getConfidenceScore`
diff --git a/textclassifier/textclassifier/api/current.txt b/textclassifier/textclassifier/api/current.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/current.txt
+++ b/textclassifier/textclassifier/api/current.txt
@@ -271,7 +271,7 @@
}
public final class TextLinksParams {
- field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+ field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
}
public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt b/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt
+++ b/textclassifier/textclassifier/api/public_plus_experimental_1.0.0-alpha03.txt
@@ -271,7 +271,7 @@
}
public final class TextLinksParams {
- field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+ field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
}
public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/public_plus_experimental_current.txt b/textclassifier/textclassifier/api/public_plus_experimental_current.txt
index 21567f3..79c4717 100644
--- a/textclassifier/textclassifier/api/public_plus_experimental_current.txt
+++ b/textclassifier/textclassifier/api/public_plus_experimental_current.txt
@@ -271,7 +271,7 @@
}
public final class TextLinksParams {
- field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+ field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
}
public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt b/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt
index 3e183d8..2ab5708 100644
--- a/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt
+++ b/textclassifier/textclassifier/api/restricted_1.0.0-alpha03.txt
@@ -318,7 +318,7 @@
}
public final class TextLinksParams {
- field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+ field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
}
public static final class TextLinksParams.Builder {
diff --git a/textclassifier/textclassifier/api/restricted_current.txt b/textclassifier/textclassifier/api/restricted_current.txt
index 3e183d8..2ab5708 100644
--- a/textclassifier/textclassifier/api/restricted_current.txt
+++ b/textclassifier/textclassifier/api/restricted_current.txt
@@ -318,7 +318,7 @@
}
public final class TextLinksParams {
- field public static final androidx.textclassifier.TextLinksParams! DEFAULT_PARAMS;
+ field public static final androidx.textclassifier.TextLinksParams DEFAULT_PARAMS;
}
public static final class TextLinksParams.Builder {
diff --git a/tv-provider/tv-provider/api/api_lint.ignore b/tv-provider/tv-provider/api/api_lint.ignore
index 7c43e2f..783a749 100644
--- a/tv-provider/tv-provider/api/api_lint.ignore
+++ b/tv-provider/tv-provider/api/api_lint.ignore
@@ -305,12 +305,6 @@
Missing nullability on method `downloadBitmap` return
MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getAllChannels():
Missing nullability on method `getAllChannels` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getPreviewChannel(long):
- Missing nullability on method `getPreviewChannel` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getPreviewProgram(long):
- Missing nullability on method `getPreviewProgram` return
-MissingNullability: androidx.tvprovider.media.tv.PreviewChannelHelper#getWatchNextProgram(long):
- Missing nullability on method `getWatchNextProgram` return
MissingNullability: androidx.tvprovider.media.tv.PreviewProgram#fromCursor(android.database.Cursor):
Missing nullability on method `fromCursor` return
MissingNullability: androidx.tvprovider.media.tv.PreviewProgram#fromCursor(android.database.Cursor) parameter #0:
diff --git a/ui/integration-tests/benchmark/build.gradle b/ui/integration-tests/benchmark/build.gradle
index 407eb1e..40db4f5 100644
--- a/ui/integration-tests/benchmark/build.gradle
+++ b/ui/integration-tests/benchmark/build.gradle
@@ -36,6 +36,7 @@
implementation project(":compose:compose-runtime")
implementation project(":ui:integration-tests")
implementation project(":ui:ui-test")
+ implementation project(":ui:ui-layout")
implementation(KOTLIN_STDLIB)
implementation(KOTLIN_REFLECT)
implementation(ANDROIDX_TEST_RULES)
diff --git a/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml b/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml
index a7345d6..1983f55 100644
--- a/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml
+++ b/ui/integration-tests/benchmark/src/androidTest/AndroidManifest.xml
@@ -23,7 +23,11 @@
~ requestLegacyExternalStorage to enable legacy JSON reporting when targeting Q
-->
<application
- android:requestLegacyExternalStorage="true"
- android:debuggable="false"
- tools:replace="android:debuggable" />
+ android:requestLegacyExternalStorage="true"
+ android:debuggable="false"
+ tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
+ </application>
</manifest>
diff --git a/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
new file mode 100644
index 0000000..e3efcc0
--- /dev/null
+++ b/ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.benchmark.test
+
+import android.view.ViewGroup
+import androidx.activity.ComponentActivity
+import androidx.benchmark.junit4.BenchmarkRule
+import androidx.benchmark.junit4.measureRepeated
+import androidx.test.filters.LargeTest
+import androidx.ui.core.AndroidOwner
+import androidx.ui.core.LayoutNode
+import androidx.ui.core.Modifier
+import androidx.ui.core.drawBehind
+import androidx.ui.core.drawLayer
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.core.keyinput.keyInputFilter
+import androidx.ui.core.layoutId
+import androidx.ui.core.onPositioned
+import androidx.ui.core.semantics.semantics
+import androidx.ui.core.setContent
+import androidx.ui.core.zIndex
+import androidx.ui.foundation.Box
+import androidx.ui.layout.padding
+import androidx.ui.test.DisableTransitions
+import androidx.ui.unit.dp
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.junit.runners.model.Statement
+
+/**
+ * Benchmark that sets the [LayoutNode.modifier].
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+class LayoutNodeModifierBenchmark(
+ private val numberOfModifiers: Int
+) {
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "modifiers={0}")
+ fun initParameters(): Array<Any> = arrayOf(1, 5, 10)
+ }
+
+ @get:Rule
+ val rule = SimpleAndroidBenchmarkRule()
+
+ var modifiers = emptyList<Modifier>()
+ var combinedModifier: Modifier = Modifier
+ lateinit var layoutNode: LayoutNode
+
+ @Before
+ fun setup() {
+ modifiers = listOf(
+ Modifier.padding(10.dp),
+ Modifier.drawBehind { },
+ Modifier.drawLayer(),
+ Modifier.keyInputFilter { _ -> true },
+ Modifier.semantics(),
+ Modifier.pressIndicatorGestureFilter(),
+ Modifier.layoutId("Hello"),
+ Modifier.padding(10.dp),
+ Modifier.onPositioned { _ -> },
+ Modifier.zIndex(1f)
+ ).subList(0, numberOfModifiers)
+
+ combinedModifier = modifiers.fold<Modifier, Modifier>(Modifier) { acc, modifier ->
+ acc + modifier
+ }
+
+ rule.activityTestRule.runOnUiThread {
+ rule.activityTestRule.activity.setContent { Box() }
+ }
+ rule.activityTestRule.runOnUiThread {
+ val composeView = rule.findAndroidOwner()
+ val root = composeView.root
+ val selection = root.children[0]
+ check(selection.children.size == 1) { "Expecting only a Box" }
+ layoutNode = selection.children[0]
+ check(layoutNode.children.isEmpty()) { "Box should be empty" }
+ }
+ }
+
+ @Test
+ fun setAndClearModifiers() {
+ rule.activityTestRule.runOnUiThread {
+ rule.benchmarkRule.measureRepeated {
+ layoutNode.modifier = combinedModifier
+ layoutNode.modifier = Modifier
+ }
+ }
+ }
+
+ @Test
+ fun smallModifierChange() {
+ rule.activityTestRule.runOnUiThread {
+ val altModifier = Modifier.padding(10.dp) + combinedModifier
+ layoutNode.modifier = altModifier
+
+ rule.benchmarkRule.measureRepeated {
+ layoutNode.modifier = combinedModifier
+ layoutNode.modifier = altModifier
+ }
+ }
+ }
+
+ class SimpleAndroidBenchmarkRule() : TestRule {
+ @Suppress("DEPRECATION")
+ val activityTestRule =
+ androidx.test.rule.ActivityTestRule<ComponentActivity>(ComponentActivity::class.java)
+
+ val benchmarkRule = BenchmarkRule()
+
+ private val disableTransitionsRule = DisableTransitions()
+
+ override fun apply(base: Statement, description: Description?): Statement {
+ val statement = benchmarkRule.apply(
+ activityTestRule.apply(base, description), description!!)
+ return disableTransitionsRule.apply(statement, description)
+ }
+
+ fun findAndroidOwner(): AndroidOwner {
+ return activityTestRule.activity.findViewById<ViewGroup>(android.R.id.content)
+ .getChildAt(0) as AndroidOwner
+ }
+ }
+}
diff --git a/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt b/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt
index e7e80c0..7bc3203 100644
--- a/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt
+++ b/ui/integration-tests/demos/src/main/java/androidx/ui/demos/DemoApp.kt
@@ -21,7 +21,9 @@
import androidx.compose.setValue
import androidx.ui.animation.Crossfade
import androidx.ui.core.Alignment
+import androidx.ui.core.LayoutDirection
import androidx.ui.core.Modifier
+import androidx.ui.core.WithConstraints
import androidx.ui.core.testTag
import androidx.ui.demos.common.ActivityDemo
import androidx.ui.demos.common.ComposableDemo
@@ -44,6 +46,7 @@
import androidx.ui.material.TopAppBar
import androidx.ui.material.icons.Icons
import androidx.ui.material.icons.filled.ArrowBack
+import androidx.ui.material.icons.filled.ArrowForward
import androidx.ui.material.icons.filled.Search
import androidx.ui.material.icons.filled.Settings
import androidx.ui.savedinstancestate.savedInstanceState
@@ -61,11 +64,7 @@
onNavigateUp: () -> Unit,
launchSettings: () -> Unit
) {
- val navigationIcon = (@Composable {
- IconButton(onClick = onNavigateUp) {
- Icon(Icons.Filled.ArrowBack)
- }
- }).takeIf { canNavigateUp }
+ val navigationIcon = (@Composable { AppBarIcons.Back(onNavigateUp) }).takeIf { canNavigateUp }
var filterText by savedInstanceState(saver = TextFieldValue.Saver) { TextFieldValue() }
@@ -173,6 +172,19 @@
private object AppBarIcons {
@Composable
+ fun Back(onClick: () -> Unit) {
+ WithConstraints {
+ val icon = when (layoutDirection) {
+ LayoutDirection.Ltr -> Icons.Filled.ArrowBack
+ LayoutDirection.Rtl -> Icons.Filled.ArrowForward
+ }
+ IconButton(onClick = onClick) {
+ Icon(icon)
+ }
+ }
+ }
+
+ @Composable
fun Filter(onClick: () -> Unit) {
IconButton(modifier = Modifier.testTag(Tags.FilterButton), onClick = onClick) {
Icon(Icons.Filled.Search)
diff --git a/ui/settings.gradle b/ui/settings.gradle
index 936c7f3..a62c916 100644
--- a/ui/settings.gradle
+++ b/ui/settings.gradle
@@ -43,6 +43,7 @@
includeProject(":compose:compose-compiler", "../compose/compose-compiler")
includeProject(":compose:compose-compiler-hosted", "../compose/compose-compiler-hosted")
includeProject(":compose:compose-compiler-hosted:integration-tests", "../compose/compose-compiler-hosted/integration-tests")
+includeProject(":compose:compose-dispatch", "../compose/compose-dispatch")
includeProject(":compose:compose-runtime", "../compose/compose-runtime")
includeProject(":compose:compose-runtime-benchmark", "../compose/compose-runtime/compose-runtime-benchmark")
includeProject(":compose:compose-runtime:samples", "../compose/compose-runtime/samples")
@@ -62,6 +63,7 @@
includeProject(":ui:ui-animation-core:samples", "ui-animation-core/samples")
includeProject(":ui:ui-animation:integration-tests:ui-animation-demos", "ui-animation/integration-tests/animation-demos")
includeProject(":ui:ui-animation:samples", "ui-animation/samples")
+includeProject(":ui:ui-animation-tooling", "ui-animation-tooling")
includeProject(":ui:ui-core", "ui-core")
includeProject(":ui:ui-core:integration-tests:ui-core-demos", "ui-core/integration-tests/ui-core-demos")
includeProject(":ui:ui-core:samples", "ui-core/samples")
diff --git a/ui/ui-android-view/build.gradle b/ui/ui-android-view/build.gradle
index efb20b7..7d716ba 100644
--- a/ui/ui-android-view/build.gradle
+++ b/ui/ui-android-view/build.gradle
@@ -62,7 +62,7 @@
androidx {
name = "AndroidX UI View components"
- publish = Publish.SNAPSHOT_AND_RELEASE
+ publish = Publish.NONE
mavenVersion = LibraryVersions.UI
mavenGroup = LibraryGroups.UI
inceptionYear = "2019"
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt
index b4b39a0..b416598 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt
+++ b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/ComplexInteractions.kt
@@ -20,7 +20,6 @@
import android.widget.FrameLayout
import androidx.compose.Composable
import androidx.compose.Recomposer
-import androidx.compose.escapeCompose
import androidx.ui.core.ContextAmbient
import androidx.ui.core.setContent
import androidx.ui.demos.common.ComposableDemo
@@ -57,12 +56,11 @@
@Composable
fun AndroidWithCompose(context: Context, children: @Composable () -> Unit) {
- val anotherLayout =
- escapeCompose { FrameLayout(context) }.also { view ->
- view.setContent(Recomposer.current()) {
- children()
- }
- view.setPadding(50, 50, 50, 50)
+ val anotherLayout = FrameLayout(context).also { view ->
+ view.setContent(Recomposer.current()) {
+ children()
}
+ view.setPadding(50, 50, 50, 50)
+ }
AndroidView(anotherLayout)
}
\ No newline at end of file
diff --git a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt
index 0bededb..400a60b 100644
--- a/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt
+++ b/ui/ui-android-view/integration-tests/android-view-demos/src/main/java/androidx/ui/androidview/demos/WebComponentActivity.kt
@@ -47,6 +47,7 @@
import androidx.ui.androidview.WebComponent
import androidx.ui.androidview.WebContext
import androidx.ui.core.setViewContent
+import androidx.ui.viewinterop.emitView
@Stable
class WebParams {
@@ -65,7 +66,7 @@
Log.e("WebCompAct", "setContent")
}
- FrameLayout {
+ emitView(::FrameLayout, {}) {
renderViews(webContext = webContext)
}
}
@@ -94,52 +95,56 @@
}
}
- LinearLayout(
- orientation = LinearLayout.VERTICAL,
- layoutWidth = MATCH_PARENT,
- layoutHeight = MATCH_PARENT
- ) {
- LinearLayout(
- orientation = LinearLayout.HORIZONTAL,
- layoutWidth = MATCH_PARENT,
- layoutHeight = WRAP_CONTENT,
- weightSum = 1f
- ) {
- Button(
- layoutWidth = 40.dp,
- layoutHeight = WRAP_CONTENT,
- text = "",
- onClick = {
+ emitView(::LinearLayout, {
+ it.orientation = LinearLayout.VERTICAL
+ it.setLayoutWidth(MATCH_PARENT)
+ it.setLayoutHeight(MATCH_PARENT)
+ }) {
+ emitView(::LinearLayout, {
+ it.orientation = LinearLayout.HORIZONTAL
+ it.setLayoutWidth(MATCH_PARENT)
+ it.setLayoutHeight(WRAP_CONTENT)
+ it.weightSum = 1f
+ }) {
+ emitView(::Button) {
+ it.setLayoutWidth(40.dp)
+ it.setLayoutHeight(WRAP_CONTENT)
+ it.text = ""
+ it.setOnClickListener {
webContext.goBack()
- })
- Button(
- layoutWidth = 40.dp,
- layoutHeight = WRAP_CONTENT,
- text = ") {",
- onClick = {
+ }
+ }
+ emitView(::Button) {
+ it.setLayoutWidth(40.dp)
+ it.setLayoutHeight(WRAP_CONTENT)
+ it.text = ""
+ it.setOnClickListener {
webContext.goForward()
- })
- EditText(
- layoutWidth = 0.dp,
- layoutHeight = WRAP_CONTENT,
- layoutWeight = 1f,
- singleLine = true,
- controlledText = displayedUrl.value,
- onTextChanged = { s: CharSequence?, _, _, _ ->
+ }
+ }
+ emitView(::EditText) {
+ it.setLayoutWidth(0.dp)
+ it.setLayoutHeight(WRAP_CONTENT)
+ it.setLayoutWeight(1f)
+ it.isSingleLine = true
+ it.setControlledText(displayedUrl.value)
+ it.setOnTextChanged { s: CharSequence?, _, _, _ ->
displayedUrl.value = s.toString()
- })
- Button(
- layoutWidth = WRAP_CONTENT,
- layoutHeight = WRAP_CONTENT,
- text = "Go",
- onClick = {
+ }
+ }
+ emitView(::Button) {
+ it.setLayoutWidth(WRAP_CONTENT)
+ it.setLayoutHeight(WRAP_CONTENT)
+ it.text = "Go"
+ it.setOnClickListener {
if (displayedUrl.value.isNotBlank()) {
if (WebContext.debug) {
Log.d("WebCompAct", "setting url to " + displayedUrl.value)
}
webParams.url = displayedUrl.value
}
- })
+ }
+ }
}
if (WebContext.debug) {
diff --git a/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt b/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt
index 5b89d14..1203662 100644
--- a/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt
+++ b/ui/ui-android-view/src/main/java/androidx/ui/androidview/WebComponent.kt
@@ -21,6 +21,7 @@
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.Composable
+import androidx.ui.viewinterop.emitView
class WebContext {
@@ -80,8 +81,9 @@
Log.d("WebComponent", "WebComponent compose " + url)
}
- WebView(
- ref = { webContext.webView = it },
- url = url,
- webViewClient = webViewClient)
+ emitView(::WebView) {
+ it.setRef { view -> webContext.webView = view }
+ it.setUrl(url)
+ it.webViewClient = webViewClient
+ }
}
diff --git a/ui/ui-animation-core/api/0.1.0-dev15.txt b/ui/ui-animation-core/api/0.1.0-dev15.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/0.1.0-dev15.txt
+++ b/ui/ui-animation-core/api/0.1.0-dev15.txt
@@ -60,6 +60,8 @@
}
public enum AnimationEndReason {
+ method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.AnimationEndReason[] values();
enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
ctor public BaseAnimationClock();
method public void subscribe(androidx.animation.AnimationClockObserver observer);
method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
- field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
+ field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
}
public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
}
public enum InterruptionHandling {
+ method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.InterruptionHandling[] values();
enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
field public static final float DampingRatioMediumBouncy = 0.5f;
field public static final float DampingRatioNoBouncy = 1.0f;
field public static final float DefaultDisplacementThreshold = 0.01f;
- field public static final androidx.animation.Spring! INSTANCE;
+ field public static final androidx.animation.Spring INSTANCE;
field public static final float StiffnessHigh = 10000.0f;
field public static final float StiffnessLow = 200.0f;
field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/api_lint.ignore b/ui/ui-animation-core/api/api_lint.ignore
index 35e0da1..a5bb439 100644
--- a/ui/ui-animation-core/api/api_lint.ignore
+++ b/ui/ui-animation-core/api/api_lint.ignore
@@ -17,8 +17,6 @@
CallbackName: androidx.animation.AnimationClockObserver:
Class should be named AnimationClockCallback
-CallbackName: androidx.animation.TransitionAnimation.TransitionAnimationClockObserver:
- Class should be named TransitionAnimationClockCallback
DocumentExceptions: androidx.animation.DurationBasedAnimationBuilder#setDelay(int):
diff --git a/ui/ui-animation-core/api/current.txt b/ui/ui-animation-core/api/current.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/current.txt
+++ b/ui/ui-animation-core/api/current.txt
@@ -60,6 +60,8 @@
}
public enum AnimationEndReason {
+ method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.AnimationEndReason[] values();
enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
ctor public BaseAnimationClock();
method public void subscribe(androidx.animation.AnimationClockObserver observer);
method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
- field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
+ field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
}
public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
}
public enum InterruptionHandling {
+ method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.InterruptionHandling[] values();
enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
field public static final float DampingRatioMediumBouncy = 0.5f;
field public static final float DampingRatioNoBouncy = 1.0f;
field public static final float DefaultDisplacementThreshold = 0.01f;
- field public static final androidx.animation.Spring! INSTANCE;
+ field public static final androidx.animation.Spring INSTANCE;
field public static final float StiffnessHigh = 10000.0f;
field public static final float StiffnessLow = 200.0f;
field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -60,6 +60,8 @@
}
public enum AnimationEndReason {
+ method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.AnimationEndReason[] values();
enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
ctor public BaseAnimationClock();
method public void subscribe(androidx.animation.AnimationClockObserver observer);
method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
- field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
+ field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
}
public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
}
public enum InterruptionHandling {
+ method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.InterruptionHandling[] values();
enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
field public static final float DampingRatioMediumBouncy = 0.5f;
field public static final float DampingRatioNoBouncy = 1.0f;
field public static final float DefaultDisplacementThreshold = 0.01f;
- field public static final androidx.animation.Spring! INSTANCE;
+ field public static final androidx.animation.Spring INSTANCE;
field public static final float StiffnessHigh = 10000.0f;
field public static final float StiffnessLow = 200.0f;
field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/public_plus_experimental_current.txt b/ui/ui-animation-core/api/public_plus_experimental_current.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-animation-core/api/public_plus_experimental_current.txt
@@ -60,6 +60,8 @@
}
public enum AnimationEndReason {
+ method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.AnimationEndReason[] values();
enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
ctor public BaseAnimationClock();
method public void subscribe(androidx.animation.AnimationClockObserver observer);
method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
- field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
+ field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
}
public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
}
public enum InterruptionHandling {
+ method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.InterruptionHandling[] values();
enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
field public static final float DampingRatioMediumBouncy = 0.5f;
field public static final float DampingRatioNoBouncy = 1.0f;
field public static final float DefaultDisplacementThreshold = 0.01f;
- field public static final androidx.animation.Spring! INSTANCE;
+ field public static final androidx.animation.Spring INSTANCE;
field public static final float StiffnessHigh = 10000.0f;
field public static final float StiffnessLow = 200.0f;
field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt b/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-animation-core/api/restricted_0.1.0-dev15.txt
@@ -60,6 +60,8 @@
}
public enum AnimationEndReason {
+ method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.AnimationEndReason[] values();
enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
ctor public BaseAnimationClock();
method public void subscribe(androidx.animation.AnimationClockObserver observer);
method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
- field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
+ field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
}
public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
}
public enum InterruptionHandling {
+ method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.InterruptionHandling[] values();
enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
field public static final float DampingRatioMediumBouncy = 0.5f;
field public static final float DampingRatioNoBouncy = 1.0f;
field public static final float DefaultDisplacementThreshold = 0.01f;
- field public static final androidx.animation.Spring! INSTANCE;
+ field public static final androidx.animation.Spring INSTANCE;
field public static final float StiffnessHigh = 10000.0f;
field public static final float StiffnessLow = 200.0f;
field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-core/api/restricted_current.txt b/ui/ui-animation-core/api/restricted_current.txt
index 5b19c68..27407b0 100644
--- a/ui/ui-animation-core/api/restricted_current.txt
+++ b/ui/ui-animation-core/api/restricted_current.txt
@@ -60,6 +60,8 @@
}
public enum AnimationEndReason {
+ method public static androidx.animation.AnimationEndReason valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.AnimationEndReason[] values();
enum_constant public static final androidx.animation.AnimationEndReason BoundReached;
enum_constant public static final androidx.animation.AnimationEndReason Interrupted;
enum_constant public static final androidx.animation.AnimationEndReason TargetReached;
@@ -169,7 +171,7 @@
ctor public BaseAnimationClock();
method public void subscribe(androidx.animation.AnimationClockObserver observer);
method public void unsubscribe(androidx.animation.AnimationClockObserver observer);
- field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion! Companion;
+ field @Deprecated public static final androidx.animation.BaseAnimationClock.Companion Companion;
}
public final class ComplexDoubleKt {
@@ -292,6 +294,8 @@
}
public enum InterruptionHandling {
+ method public static androidx.animation.InterruptionHandling valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.animation.InterruptionHandling[] values();
enum_constant public static final androidx.animation.InterruptionHandling PHYSICS;
enum_constant public static final androidx.animation.InterruptionHandling SNAP_TO_END;
enum_constant public static final androidx.animation.InterruptionHandling TWEEN;
@@ -394,7 +398,7 @@
field public static final float DampingRatioMediumBouncy = 0.5f;
field public static final float DampingRatioNoBouncy = 1.0f;
field public static final float DefaultDisplacementThreshold = 0.01f;
- field public static final androidx.animation.Spring! INSTANCE;
+ field public static final androidx.animation.Spring INSTANCE;
field public static final float StiffnessHigh = 10000.0f;
field public static final float StiffnessLow = 200.0f;
field public static final float StiffnessMedium = 1500.0f;
diff --git a/ui/ui-animation-tooling/OWNERS b/ui/ui-animation-tooling/OWNERS
new file mode 100644
index 0000000..13f1a9c
--- /dev/null
+++ b/ui/ui-animation-tooling/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
\ No newline at end of file
diff --git a/ui/ui-animation-tooling/api/0.1.0-dev15.txt b/ui/ui-animation-tooling/api/0.1.0-dev15.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/0.1.0-dev15.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+ public interface ComposeAnimation {
+ method public Object getAnimation();
+ method public default java.util.Set<java.lang.Object> getStates();
+ method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+ }
+
+ public enum ComposeAnimationType {
+ method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+ }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/current.txt b/ui/ui-animation-tooling/api/current.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+ public interface ComposeAnimation {
+ method public Object getAnimation();
+ method public default java.util.Set<java.lang.Object> getStates();
+ method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+ }
+
+ public enum ComposeAnimationType {
+ method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+ }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-animation-tooling/api/public_plus_experimental_0.1.0-dev15.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/public_plus_experimental_0.1.0-dev15.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+ public interface ComposeAnimation {
+ method public Object getAnimation();
+ method public default java.util.Set<java.lang.Object> getStates();
+ method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+ }
+
+ public enum ComposeAnimationType {
+ method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+ }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/public_plus_experimental_current.txt b/ui/ui-animation-tooling/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/public_plus_experimental_current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+ public interface ComposeAnimation {
+ method public Object getAnimation();
+ method public default java.util.Set<java.lang.Object> getStates();
+ method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+ }
+
+ public enum ComposeAnimationType {
+ method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+ }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/restricted_0.1.0-dev15.txt b/ui/ui-animation-tooling/api/restricted_0.1.0-dev15.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/restricted_0.1.0-dev15.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+ public interface ComposeAnimation {
+ method public Object getAnimation();
+ method public default java.util.Set<java.lang.Object> getStates();
+ method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+ }
+
+ public enum ComposeAnimationType {
+ method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+ }
+
+}
+
diff --git a/ui/ui-animation-tooling/api/restricted_current.txt b/ui/ui-animation-tooling/api/restricted_current.txt
new file mode 100644
index 0000000..848e918
--- /dev/null
+++ b/ui/ui-animation-tooling/api/restricted_current.txt
@@ -0,0 +1,18 @@
+// Signature format: 3.0
+package androidx.ui.animation.tooling {
+
+ public interface ComposeAnimation {
+ method public Object getAnimation();
+ method public default java.util.Set<java.lang.Object> getStates();
+ method public androidx.ui.animation.tooling.ComposeAnimationType getType();
+ }
+
+ public enum ComposeAnimationType {
+ method public static androidx.ui.animation.tooling.ComposeAnimationType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.animation.tooling.ComposeAnimationType[] values();
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType ANIMATED_VALUE;
+ enum_constant public static final androidx.ui.animation.tooling.ComposeAnimationType TRANSITION_ANIMATION;
+ }
+
+}
+
diff --git a/ui/ui-animation-tooling/build.gradle b/ui/ui-animation-tooling/build.gradle
new file mode 100644
index 0000000..9dea25f
--- /dev/null
+++ b/ui/ui-animation-tooling/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+
+import static androidx.build.dependencies.DependenciesKt.getKOTLIN_STDLIB
+
+plugins {
+ id("AndroidXPlugin")
+ id("kotlin")
+}
+
+dependencies {
+ implementation(KOTLIN_STDLIB)
+}
+
+androidx {
+ name = "Compose Animation Tooling"
+ publish = Publish.SNAPSHOT_AND_RELEASE
+ mavenVersion = LibraryVersions.UI
+ mavenGroup = LibraryGroups.UI
+ generateDocs = false
+}
diff --git a/ui/ui-animation-tooling/src/main/java/androidx/ui/animation/tooling/ComposeAnimation.kt b/ui/ui-animation-tooling/src/main/java/androidx/ui/animation/tooling/ComposeAnimation.kt
new file mode 100644
index 0000000..bffdb24
--- /dev/null
+++ b/ui/ui-animation-tooling/src/main/java/androidx/ui/animation/tooling/ComposeAnimation.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.animation.tooling
+
+/**
+ * Type of the animation. Different types might have different properties, for example a
+ * `TransitionAnimation` (represented by [TRANSITION_ANIMATION]) has a set of states associated
+ * with it.
+ */
+enum class ComposeAnimationType {
+ TRANSITION_ANIMATION, ANIMATED_VALUE
+}
+
+/**
+ * Simple interface to make it easier to share Compose animation objects between `ui-tooling` and
+ * Android Studio. Since both ends communicate mostly using bytecode manipulation and reflection,
+ * being able to parse these objects into a common type makes
+ */
+interface ComposeAnimation {
+
+ /**
+ * Returns the animation type. Ideally, the type should be checked before calling methods
+ * specific to a certain type, e.g. [getStates].
+ */
+ fun getType(): ComposeAnimationType
+
+ /**
+ * Returns the actual animation object.
+ */
+ fun getAnimation(): Any
+
+ /**
+ * Returns all the available states of a `TransitionAnimation`.
+ *
+ * @throws UnsupportedOperationException if [getType] does not return `TRANSITION_ANIMATION`.
+ */
+ fun getStates(): Set<Any> {
+ throw UnsupportedOperationException("Only available when getType() is TRANSITION_ANIMATION")
+ }
+}
diff --git a/ui/ui-core/api/0.1.0-dev15.txt b/ui/ui-core/api/0.1.0-dev15.txt
index 0b0b3f7..634d280 100644
--- a/ui/ui-core/api/0.1.0-dev15.txt
+++ b/ui/ui-core/api/0.1.0-dev15.txt
@@ -1,12 +1,4 @@
// Signature format: 3.0
-package androidx.compose {
-
- public final class ComposerCompatKt {
- method @Deprecated public static androidx.ui.node.UiComposer getComposer();
- }
-
-}
-
package androidx.ui.autofill {
public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
}
public enum AutofillType {
+ method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.autofill.AutofillType[] values();
enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
@androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
- field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+ field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
}
public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
@androidx.compose.Immutable public interface Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
- field public static final androidx.ui.core.Alignment.Companion! Companion;
+ field public static final androidx.ui.core.Alignment.Companion Companion;
}
public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
}
@androidx.compose.Immutable public abstract sealed class AlignmentLine {
- field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+ field public static final androidx.ui.core.AlignmentLine.Companion Companion;
field public static final int Unspecified = -2147483648; // 0x80000000
}
@@ -256,7 +250,7 @@
@androidx.compose.Stable public interface ContentScale {
method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
- field public static final androidx.ui.core.ContentScale.Companion! Companion;
+ field public static final androidx.ui.core.ContentScale.Companion Companion;
}
public static final class ContentScale.Companion {
@@ -290,6 +284,8 @@
}
public enum Direction {
+ method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.Direction[] values();
enum_constant public static final androidx.ui.core.Direction DOWN;
enum_constant public static final androidx.ui.core.Direction LEFT;
enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -342,6 +338,8 @@
}
public enum DropDownAlignment {
+ method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.DropDownAlignment[] values();
enum_constant public static final androidx.ui.core.DropDownAlignment End;
enum_constant public static final androidx.ui.core.DropDownAlignment Start;
}
@@ -423,7 +421,6 @@
method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
- method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
}
@@ -445,7 +442,6 @@
method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
method public androidx.ui.core.LayoutCoordinates getCoordinates();
method public int getDepth();
- method @Deprecated public boolean getHandlesParentData();
method public int getHeight();
method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -476,7 +472,6 @@
method public void requestRemeasure();
method @Deprecated public void setCanMultiMeasure(boolean p);
method public void setDepth(int p);
- method @Deprecated public void setHandlesParentData(boolean p);
method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
method public void setModifier(androidx.ui.core.Modifier value);
method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
@@ -486,7 +481,6 @@
property public final java.util.List<androidx.ui.core.LayoutNode> children;
property public final androidx.ui.core.LayoutCoordinates coordinates;
property public final int depth;
- property @Deprecated public final boolean handlesParentData;
property public final int height;
property public final boolean isPlaced;
property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -503,6 +497,8 @@
}
public enum LayoutNode.LayoutState {
+ method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutNode.LayoutState[] values();
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
@@ -584,7 +580,7 @@
method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
- field public static final androidx.ui.core.Modifier.Companion! Companion;
+ field public static final androidx.ui.core.Modifier.Companion Companion;
}
public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -634,12 +630,15 @@
method public void drawLayer(androidx.ui.graphics.Canvas canvas);
method public long getLayerId();
method public android.graphics.Matrix getMatrix();
+ method public androidx.ui.core.DrawLayerModifier getModifier();
method public void invalidate();
method public void move(androidx.ui.unit.IntOffset position);
method public void resize(androidx.ui.unit.IntSize size);
+ method public void setModifier(androidx.ui.core.DrawLayerModifier p);
method public void updateDisplayList();
method public void updateLayerProperties();
property public abstract long layerId;
+ property public abstract androidx.ui.core.DrawLayerModifier modifier;
}
public interface Owner {
@@ -684,7 +683,7 @@
property public abstract boolean showLayoutBounds;
property public abstract androidx.ui.input.TextInputService textInputService;
property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
- field public static final androidx.ui.core.Owner.Companion! Companion;
+ field public static final androidx.ui.core.Owner.Companion Companion;
}
public static final class Owner.Companion {
@@ -734,6 +733,8 @@
}
public enum PointerEventPass {
+ method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.PointerEventPass[] values();
enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -813,7 +814,6 @@
}
public final class TestTagKt {
- method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
}
@@ -826,7 +826,7 @@
method public static float getPivotFractionY-impl(long $this);
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method @androidx.compose.Immutable public static inline String! toString-impl(long p);
- field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+ field public static final androidx.ui.core.TransformOrigin.Companion Companion;
}
public static final class TransformOrigin.Companion {
@@ -859,8 +859,8 @@
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
}
public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -889,6 +889,8 @@
package androidx.ui.core.focus {
public enum FocusDetailedState {
+ method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusDetailedState[] values();
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -913,6 +915,8 @@
}
public enum FocusState {
+ method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusState[] values();
enum_constant public static final androidx.ui.core.focus.FocusState Focused;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -962,7 +966,10 @@
}
public final class DragSlopExceededGestureFilterKt {
- method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+ method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+ }
+
+ @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
}
public final class GestureUtilsKt {
@@ -990,7 +997,7 @@
}
public final class RawDragGestureFilterKt {
- method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+ method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
}
public final class RawPressStartGestureFilterKt {
@@ -1026,6 +1033,17 @@
public final class ScaleUtilKt {
}
+ public interface ScrollCallback {
+ method public default void onCancel();
+ method public default float onScroll(float scrollDistance);
+ method public default void onStart(androidx.ui.geometry.Offset downPosition);
+ method public default void onStop(float velocity);
+ }
+
+ public final class ScrollGestureFilterKt {
+ method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+ }
+
public final class TapGestureFilterKt {
method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
}
@@ -1045,13 +1063,36 @@
}
public enum DelayUpMessage {
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
}
public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
- field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+ field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+ }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+ public enum Orientation {
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+ }
+
+ @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+ ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+ method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public void onCancel();
+ method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
}
}
@@ -1080,6 +1121,8 @@
}
public enum HapticFeedbackType {
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
}
@@ -1113,7 +1156,7 @@
method public int getKeyCode();
method public static inline int hashCode-impl(int p);
method public static String toString-impl(int $this);
- field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+ field public static final androidx.ui.core.keyinput.Key.Companion Companion;
}
public static final class Key.Companion {
@@ -1706,6 +1749,8 @@
}
public enum KeyEventType {
+ method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.keyinput.KeyEventType[] values();
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
}
@@ -1789,6 +1834,9 @@
public final class SelectionHandlesKt {
}
+ public final class SelectionLayoutKt {
+ }
+
public final class SelectionManagerKt {
}
@@ -1838,19 +1886,18 @@
}
public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
- method public boolean getApplyToChildLayoutNode();
method public int getId();
method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
- property public abstract boolean applyToChildLayoutNode;
property public abstract int id;
property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
}
public final class SemanticsModifierKt {
- method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+ method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
}
public final class SemanticsNode {
+ method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
method public androidx.ui.unit.PxBounds getBoundsInRoot();
method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1873,7 +1920,7 @@
property public final boolean isRoot;
property public final androidx.ui.core.semantics.SemanticsNode? parent;
property public final androidx.ui.unit.IntSize size;
- field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+ field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
}
public static final class SemanticsNode.Companion {
@@ -1907,6 +1954,8 @@
}
public enum TextToolbarStatus {
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
}
@@ -1927,6 +1976,13 @@
method public final void invalidate();
}
+ public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+ ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+ method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ }
+
public final class VectorAsset {
method public String component1();
method public float component2();
@@ -1961,8 +2017,8 @@
}
public final class VectorComposeKt {
- method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
- method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+ method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
}
public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2015,7 +2071,7 @@
public final class VectorPainterKt {
method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
- method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+ method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
field public static final String RootGroupName = "VectorRootGroup";
}
@@ -2044,9 +2100,6 @@
method public float getStrokeLineWidth();
}
- public final class VectorScope {
- }
-
}
package androidx.ui.graphics.vector.compat {
@@ -2074,17 +2127,16 @@
public final class PointerInteropUtilsKt {
}
- public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
- ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
- method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public android.content.Context getContext();
- method public Object getRoot();
- }
-
- public final class UiComposerKt {
+ public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+ ctor public UiApplier(Object root);
+ method public void down(Object node);
+ method public Object getCurrent();
+ method public void insert(int index, Object instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ method public void reset();
+ method public void up();
+ property public Object current;
}
public final class ViewInteropKt {
@@ -2209,11 +2261,7 @@
property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
- field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
- }
-
- public final class SemanticsKt {
- method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
}
public final class SemanticsProperties {
@@ -2233,7 +2281,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
- field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+ field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
}
public final class SemanticsPropertiesKt {
@@ -2329,6 +2377,11 @@
method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
}
+ public final class EmitViewKt {
+ method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+ method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ }
+
}
package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/api_lint.ignore b/ui/ui-core/api/api_lint.ignore
index 158eb11..4151ff7 100644
--- a/ui/ui-core/api/api_lint.ignore
+++ b/ui/ui-core/api/api_lint.ignore
@@ -29,8 +29,12 @@
Class should be named ScaleCallback
-ContextFirst: androidx.ui.core.WrapperKt#subcomposeInto(androidx.ui.core.LayoutNode, android.content.Context, androidx.compose.CompositionReference, kotlin.jvm.functions.Function0<kotlin.Unit>) parameter #1:
- Context is distinct, so it must be the first argument (method `subcomposeInto`)
+ListenerLast: androidx.ui.core.gesture.ScrollGestureFilterKt#scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>, boolean) parameter #2:
+ Listeners should always be at end of argument list (method `scrollGestureFilter`)
+ListenerLast: androidx.ui.core.gesture.ScrollGestureFilterKt#scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>, boolean) parameter #3:
+ Listeners should always be at end of argument list (method `scrollGestureFilter`)
+ListenerLast: androidx.ui.core.gesture.ScrollGestureFilterKt#scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>, boolean) parameter #4:
+ Listeners should always be at end of argument list (method `scrollGestureFilter`)
MissingNullability: androidx.ui.core.Measured#constructor-impl(androidx.ui.core.Placeable):
diff --git a/ui/ui-core/api/current.txt b/ui/ui-core/api/current.txt
index 0b0b3f7..634d280 100644
--- a/ui/ui-core/api/current.txt
+++ b/ui/ui-core/api/current.txt
@@ -1,12 +1,4 @@
// Signature format: 3.0
-package androidx.compose {
-
- public final class ComposerCompatKt {
- method @Deprecated public static androidx.ui.node.UiComposer getComposer();
- }
-
-}
-
package androidx.ui.autofill {
public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
}
public enum AutofillType {
+ method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.autofill.AutofillType[] values();
enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
@androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
- field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+ field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
}
public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
@androidx.compose.Immutable public interface Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
- field public static final androidx.ui.core.Alignment.Companion! Companion;
+ field public static final androidx.ui.core.Alignment.Companion Companion;
}
public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
}
@androidx.compose.Immutable public abstract sealed class AlignmentLine {
- field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+ field public static final androidx.ui.core.AlignmentLine.Companion Companion;
field public static final int Unspecified = -2147483648; // 0x80000000
}
@@ -256,7 +250,7 @@
@androidx.compose.Stable public interface ContentScale {
method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
- field public static final androidx.ui.core.ContentScale.Companion! Companion;
+ field public static final androidx.ui.core.ContentScale.Companion Companion;
}
public static final class ContentScale.Companion {
@@ -290,6 +284,8 @@
}
public enum Direction {
+ method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.Direction[] values();
enum_constant public static final androidx.ui.core.Direction DOWN;
enum_constant public static final androidx.ui.core.Direction LEFT;
enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -342,6 +338,8 @@
}
public enum DropDownAlignment {
+ method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.DropDownAlignment[] values();
enum_constant public static final androidx.ui.core.DropDownAlignment End;
enum_constant public static final androidx.ui.core.DropDownAlignment Start;
}
@@ -423,7 +421,6 @@
method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
- method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
}
@@ -445,7 +442,6 @@
method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
method public androidx.ui.core.LayoutCoordinates getCoordinates();
method public int getDepth();
- method @Deprecated public boolean getHandlesParentData();
method public int getHeight();
method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -476,7 +472,6 @@
method public void requestRemeasure();
method @Deprecated public void setCanMultiMeasure(boolean p);
method public void setDepth(int p);
- method @Deprecated public void setHandlesParentData(boolean p);
method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
method public void setModifier(androidx.ui.core.Modifier value);
method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
@@ -486,7 +481,6 @@
property public final java.util.List<androidx.ui.core.LayoutNode> children;
property public final androidx.ui.core.LayoutCoordinates coordinates;
property public final int depth;
- property @Deprecated public final boolean handlesParentData;
property public final int height;
property public final boolean isPlaced;
property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -503,6 +497,8 @@
}
public enum LayoutNode.LayoutState {
+ method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutNode.LayoutState[] values();
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
@@ -584,7 +580,7 @@
method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
- field public static final androidx.ui.core.Modifier.Companion! Companion;
+ field public static final androidx.ui.core.Modifier.Companion Companion;
}
public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -634,12 +630,15 @@
method public void drawLayer(androidx.ui.graphics.Canvas canvas);
method public long getLayerId();
method public android.graphics.Matrix getMatrix();
+ method public androidx.ui.core.DrawLayerModifier getModifier();
method public void invalidate();
method public void move(androidx.ui.unit.IntOffset position);
method public void resize(androidx.ui.unit.IntSize size);
+ method public void setModifier(androidx.ui.core.DrawLayerModifier p);
method public void updateDisplayList();
method public void updateLayerProperties();
property public abstract long layerId;
+ property public abstract androidx.ui.core.DrawLayerModifier modifier;
}
public interface Owner {
@@ -684,7 +683,7 @@
property public abstract boolean showLayoutBounds;
property public abstract androidx.ui.input.TextInputService textInputService;
property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
- field public static final androidx.ui.core.Owner.Companion! Companion;
+ field public static final androidx.ui.core.Owner.Companion Companion;
}
public static final class Owner.Companion {
@@ -734,6 +733,8 @@
}
public enum PointerEventPass {
+ method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.PointerEventPass[] values();
enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -813,7 +814,6 @@
}
public final class TestTagKt {
- method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
}
@@ -826,7 +826,7 @@
method public static float getPivotFractionY-impl(long $this);
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method @androidx.compose.Immutable public static inline String! toString-impl(long p);
- field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+ field public static final androidx.ui.core.TransformOrigin.Companion Companion;
}
public static final class TransformOrigin.Companion {
@@ -859,8 +859,8 @@
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
}
public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -889,6 +889,8 @@
package androidx.ui.core.focus {
public enum FocusDetailedState {
+ method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusDetailedState[] values();
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -913,6 +915,8 @@
}
public enum FocusState {
+ method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusState[] values();
enum_constant public static final androidx.ui.core.focus.FocusState Focused;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -962,7 +966,10 @@
}
public final class DragSlopExceededGestureFilterKt {
- method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+ method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+ }
+
+ @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
}
public final class GestureUtilsKt {
@@ -990,7 +997,7 @@
}
public final class RawDragGestureFilterKt {
- method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+ method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
}
public final class RawPressStartGestureFilterKt {
@@ -1026,6 +1033,17 @@
public final class ScaleUtilKt {
}
+ public interface ScrollCallback {
+ method public default void onCancel();
+ method public default float onScroll(float scrollDistance);
+ method public default void onStart(androidx.ui.geometry.Offset downPosition);
+ method public default void onStop(float velocity);
+ }
+
+ public final class ScrollGestureFilterKt {
+ method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+ }
+
public final class TapGestureFilterKt {
method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
}
@@ -1045,13 +1063,36 @@
}
public enum DelayUpMessage {
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
}
public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
- field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+ field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+ }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+ public enum Orientation {
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+ }
+
+ @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+ ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+ method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public void onCancel();
+ method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
}
}
@@ -1080,6 +1121,8 @@
}
public enum HapticFeedbackType {
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
}
@@ -1113,7 +1156,7 @@
method public int getKeyCode();
method public static inline int hashCode-impl(int p);
method public static String toString-impl(int $this);
- field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+ field public static final androidx.ui.core.keyinput.Key.Companion Companion;
}
public static final class Key.Companion {
@@ -1706,6 +1749,8 @@
}
public enum KeyEventType {
+ method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.keyinput.KeyEventType[] values();
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
}
@@ -1789,6 +1834,9 @@
public final class SelectionHandlesKt {
}
+ public final class SelectionLayoutKt {
+ }
+
public final class SelectionManagerKt {
}
@@ -1838,19 +1886,18 @@
}
public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
- method public boolean getApplyToChildLayoutNode();
method public int getId();
method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
- property public abstract boolean applyToChildLayoutNode;
property public abstract int id;
property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
}
public final class SemanticsModifierKt {
- method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+ method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
}
public final class SemanticsNode {
+ method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
method public androidx.ui.unit.PxBounds getBoundsInRoot();
method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1873,7 +1920,7 @@
property public final boolean isRoot;
property public final androidx.ui.core.semantics.SemanticsNode? parent;
property public final androidx.ui.unit.IntSize size;
- field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+ field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
}
public static final class SemanticsNode.Companion {
@@ -1907,6 +1954,8 @@
}
public enum TextToolbarStatus {
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
}
@@ -1927,6 +1976,13 @@
method public final void invalidate();
}
+ public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+ ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+ method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ }
+
public final class VectorAsset {
method public String component1();
method public float component2();
@@ -1961,8 +2017,8 @@
}
public final class VectorComposeKt {
- method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
- method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+ method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
}
public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2015,7 +2071,7 @@
public final class VectorPainterKt {
method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
- method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+ method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
field public static final String RootGroupName = "VectorRootGroup";
}
@@ -2044,9 +2100,6 @@
method public float getStrokeLineWidth();
}
- public final class VectorScope {
- }
-
}
package androidx.ui.graphics.vector.compat {
@@ -2074,17 +2127,16 @@
public final class PointerInteropUtilsKt {
}
- public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
- ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
- method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public android.content.Context getContext();
- method public Object getRoot();
- }
-
- public final class UiComposerKt {
+ public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+ ctor public UiApplier(Object root);
+ method public void down(Object node);
+ method public Object getCurrent();
+ method public void insert(int index, Object instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ method public void reset();
+ method public void up();
+ property public Object current;
}
public final class ViewInteropKt {
@@ -2209,11 +2261,7 @@
property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
- field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
- }
-
- public final class SemanticsKt {
- method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
}
public final class SemanticsProperties {
@@ -2233,7 +2281,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
- field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+ field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
}
public final class SemanticsPropertiesKt {
@@ -2329,6 +2377,11 @@
method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
}
+ public final class EmitViewKt {
+ method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+ method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ }
+
}
package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
index 905873c..0e76587 100644
--- a/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -1,12 +1,4 @@
// Signature format: 3.0
-package androidx.compose {
-
- public final class ComposerCompatKt {
- method @Deprecated public static androidx.ui.node.UiComposer getComposer();
- }
-
-}
-
package androidx.ui.autofill {
public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
}
public enum AutofillType {
+ method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.autofill.AutofillType[] values();
enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
@androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
- field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+ field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
}
public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
@androidx.compose.Immutable public interface Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
- field public static final androidx.ui.core.Alignment.Companion! Companion;
+ field public static final androidx.ui.core.Alignment.Companion Companion;
}
public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
}
@androidx.compose.Immutable public abstract sealed class AlignmentLine {
- field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+ field public static final androidx.ui.core.AlignmentLine.Companion Companion;
field public static final int Unspecified = -2147483648; // 0x80000000
}
@@ -256,7 +250,7 @@
@androidx.compose.Stable public interface ContentScale {
method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
- field public static final androidx.ui.core.ContentScale.Companion! Companion;
+ field public static final androidx.ui.core.ContentScale.Companion Companion;
}
public static final class ContentScale.Companion {
@@ -291,6 +285,8 @@
}
public enum Direction {
+ method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.Direction[] values();
enum_constant public static final androidx.ui.core.Direction DOWN;
enum_constant public static final androidx.ui.core.Direction LEFT;
enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -343,6 +339,8 @@
}
public enum DropDownAlignment {
+ method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.DropDownAlignment[] values();
enum_constant public static final androidx.ui.core.DropDownAlignment End;
enum_constant public static final androidx.ui.core.DropDownAlignment Start;
}
@@ -424,7 +422,6 @@
method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
- method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
}
@@ -446,7 +443,6 @@
method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
method public androidx.ui.core.LayoutCoordinates getCoordinates();
method public int getDepth();
- method @Deprecated public boolean getHandlesParentData();
method public int getHeight();
method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -477,7 +473,6 @@
method public void requestRemeasure();
method @Deprecated public void setCanMultiMeasure(boolean p);
method public void setDepth(int p);
- method @Deprecated public void setHandlesParentData(boolean p);
method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
method public void setModifier(androidx.ui.core.Modifier value);
method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
@@ -487,7 +482,6 @@
property public final java.util.List<androidx.ui.core.LayoutNode> children;
property public final androidx.ui.core.LayoutCoordinates coordinates;
property public final int depth;
- property @Deprecated public final boolean handlesParentData;
property public final int height;
property public final boolean isPlaced;
property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -504,6 +498,8 @@
}
public enum LayoutNode.LayoutState {
+ method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutNode.LayoutState[] values();
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
@@ -585,7 +581,7 @@
method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
- field public static final androidx.ui.core.Modifier.Companion! Companion;
+ field public static final androidx.ui.core.Modifier.Companion Companion;
}
public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -635,12 +631,15 @@
method public void drawLayer(androidx.ui.graphics.Canvas canvas);
method public long getLayerId();
method public android.graphics.Matrix getMatrix();
+ method public androidx.ui.core.DrawLayerModifier getModifier();
method public void invalidate();
method public void move(androidx.ui.unit.IntOffset position);
method public void resize(androidx.ui.unit.IntSize size);
+ method public void setModifier(androidx.ui.core.DrawLayerModifier p);
method public void updateDisplayList();
method public void updateLayerProperties();
property public abstract long layerId;
+ property public abstract androidx.ui.core.DrawLayerModifier modifier;
}
public interface Owner {
@@ -686,7 +685,7 @@
property public abstract boolean showLayoutBounds;
property public abstract androidx.ui.input.TextInputService textInputService;
property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
- field public static final androidx.ui.core.Owner.Companion! Companion;
+ field public static final androidx.ui.core.Owner.Companion Companion;
}
public static final class Owner.Companion {
@@ -736,6 +735,8 @@
}
public enum PointerEventPass {
+ method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.PointerEventPass[] values();
enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -815,7 +816,6 @@
}
public final class TestTagKt {
- method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
}
@@ -828,7 +828,7 @@
method public static float getPivotFractionY-impl(long $this);
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method @androidx.compose.Immutable public static inline String! toString-impl(long p);
- field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+ field public static final androidx.ui.core.TransformOrigin.Companion Companion;
}
public static final class TransformOrigin.Companion {
@@ -861,8 +861,8 @@
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
}
public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -891,6 +891,8 @@
package androidx.ui.core.focus {
public enum FocusDetailedState {
+ method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusDetailedState[] values();
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -915,6 +917,8 @@
}
public enum FocusState {
+ method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusState[] values();
enum_constant public static final androidx.ui.core.focus.FocusState Focused;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -964,7 +968,10 @@
}
public final class DragSlopExceededGestureFilterKt {
- method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+ method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+ }
+
+ @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
}
public final class GestureUtilsKt {
@@ -992,7 +999,7 @@
}
public final class RawDragGestureFilterKt {
- method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+ method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
}
public final class RawPressStartGestureFilterKt {
@@ -1028,6 +1035,17 @@
public final class ScaleUtilKt {
}
+ public interface ScrollCallback {
+ method public default void onCancel();
+ method public default float onScroll(float scrollDistance);
+ method public default void onStart(androidx.ui.geometry.Offset downPosition);
+ method public default void onStop(float velocity);
+ }
+
+ public final class ScrollGestureFilterKt {
+ method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+ }
+
public final class TapGestureFilterKt {
method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
}
@@ -1047,13 +1065,36 @@
}
public enum DelayUpMessage {
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
}
public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
- field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+ field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+ }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+ public enum Orientation {
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+ }
+
+ @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+ ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+ method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public void onCancel();
+ method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
}
}
@@ -1082,6 +1123,8 @@
}
public enum HapticFeedbackType {
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
}
@@ -1115,7 +1158,7 @@
method public int getKeyCode();
method public static inline int hashCode-impl(int p);
method public static String toString-impl(int $this);
- field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+ field public static final androidx.ui.core.keyinput.Key.Companion Companion;
}
public static final class Key.Companion {
@@ -1708,6 +1751,8 @@
}
public enum KeyEventType {
+ method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.keyinput.KeyEventType[] values();
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
}
@@ -1791,6 +1836,9 @@
public final class SelectionHandlesKt {
}
+ public final class SelectionLayoutKt {
+ }
+
public final class SelectionManagerKt {
}
@@ -1840,19 +1888,18 @@
}
public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
- method public boolean getApplyToChildLayoutNode();
method public int getId();
method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
- property public abstract boolean applyToChildLayoutNode;
property public abstract int id;
property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
}
public final class SemanticsModifierKt {
- method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+ method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
}
public final class SemanticsNode {
+ method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
method public androidx.ui.unit.PxBounds getBoundsInRoot();
method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1875,7 +1922,7 @@
property public final boolean isRoot;
property public final androidx.ui.core.semantics.SemanticsNode? parent;
property public final androidx.ui.unit.IntSize size;
- field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+ field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
}
public static final class SemanticsNode.Companion {
@@ -1909,6 +1956,8 @@
}
public enum TextToolbarStatus {
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
}
@@ -1929,6 +1978,13 @@
method public final void invalidate();
}
+ public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+ ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+ method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ }
+
public final class VectorAsset {
method public String component1();
method public float component2();
@@ -1963,8 +2019,8 @@
}
public final class VectorComposeKt {
- method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
- method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+ method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
}
public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2017,7 +2073,7 @@
public final class VectorPainterKt {
method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
- method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+ method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
field public static final String RootGroupName = "VectorRootGroup";
}
@@ -2046,9 +2102,6 @@
method public float getStrokeLineWidth();
}
- public final class VectorScope {
- }
-
}
package androidx.ui.graphics.vector.compat {
@@ -2076,17 +2129,16 @@
public final class PointerInteropUtilsKt {
}
- public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
- ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
- method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public android.content.Context getContext();
- method public Object getRoot();
- }
-
- public final class UiComposerKt {
+ public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+ ctor public UiApplier(Object root);
+ method public void down(Object node);
+ method public Object getCurrent();
+ method public void insert(int index, Object instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ method public void reset();
+ method public void up();
+ property public Object current;
}
public final class ViewInteropKt {
@@ -2211,11 +2263,7 @@
property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
- field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
- }
-
- public final class SemanticsKt {
- method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
}
public final class SemanticsProperties {
@@ -2235,7 +2283,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
- field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+ field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
}
public final class SemanticsPropertiesKt {
@@ -2331,6 +2379,11 @@
method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
}
+ public final class EmitViewKt {
+ method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+ method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ }
+
}
package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/public_plus_experimental_current.txt b/ui/ui-core/api/public_plus_experimental_current.txt
index 905873c..0e76587 100644
--- a/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-core/api/public_plus_experimental_current.txt
@@ -1,12 +1,4 @@
// Signature format: 3.0
-package androidx.compose {
-
- public final class ComposerCompatKt {
- method @Deprecated public static androidx.ui.node.UiComposer getComposer();
- }
-
-}
-
package androidx.ui.autofill {
public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
}
public enum AutofillType {
+ method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.autofill.AutofillType[] values();
enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
@androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
- field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+ field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
}
public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
@androidx.compose.Immutable public interface Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
- field public static final androidx.ui.core.Alignment.Companion! Companion;
+ field public static final androidx.ui.core.Alignment.Companion Companion;
}
public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
}
@androidx.compose.Immutable public abstract sealed class AlignmentLine {
- field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+ field public static final androidx.ui.core.AlignmentLine.Companion Companion;
field public static final int Unspecified = -2147483648; // 0x80000000
}
@@ -256,7 +250,7 @@
@androidx.compose.Stable public interface ContentScale {
method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
- field public static final androidx.ui.core.ContentScale.Companion! Companion;
+ field public static final androidx.ui.core.ContentScale.Companion Companion;
}
public static final class ContentScale.Companion {
@@ -291,6 +285,8 @@
}
public enum Direction {
+ method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.Direction[] values();
enum_constant public static final androidx.ui.core.Direction DOWN;
enum_constant public static final androidx.ui.core.Direction LEFT;
enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -343,6 +339,8 @@
}
public enum DropDownAlignment {
+ method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.DropDownAlignment[] values();
enum_constant public static final androidx.ui.core.DropDownAlignment End;
enum_constant public static final androidx.ui.core.DropDownAlignment Start;
}
@@ -424,7 +422,6 @@
method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
- method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
}
@@ -446,7 +443,6 @@
method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
method public androidx.ui.core.LayoutCoordinates getCoordinates();
method public int getDepth();
- method @Deprecated public boolean getHandlesParentData();
method public int getHeight();
method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -477,7 +473,6 @@
method public void requestRemeasure();
method @Deprecated public void setCanMultiMeasure(boolean p);
method public void setDepth(int p);
- method @Deprecated public void setHandlesParentData(boolean p);
method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
method public void setModifier(androidx.ui.core.Modifier value);
method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
@@ -487,7 +482,6 @@
property public final java.util.List<androidx.ui.core.LayoutNode> children;
property public final androidx.ui.core.LayoutCoordinates coordinates;
property public final int depth;
- property @Deprecated public final boolean handlesParentData;
property public final int height;
property public final boolean isPlaced;
property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -504,6 +498,8 @@
}
public enum LayoutNode.LayoutState {
+ method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutNode.LayoutState[] values();
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
@@ -585,7 +581,7 @@
method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
- field public static final androidx.ui.core.Modifier.Companion! Companion;
+ field public static final androidx.ui.core.Modifier.Companion Companion;
}
public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -635,12 +631,15 @@
method public void drawLayer(androidx.ui.graphics.Canvas canvas);
method public long getLayerId();
method public android.graphics.Matrix getMatrix();
+ method public androidx.ui.core.DrawLayerModifier getModifier();
method public void invalidate();
method public void move(androidx.ui.unit.IntOffset position);
method public void resize(androidx.ui.unit.IntSize size);
+ method public void setModifier(androidx.ui.core.DrawLayerModifier p);
method public void updateDisplayList();
method public void updateLayerProperties();
property public abstract long layerId;
+ property public abstract androidx.ui.core.DrawLayerModifier modifier;
}
public interface Owner {
@@ -686,7 +685,7 @@
property public abstract boolean showLayoutBounds;
property public abstract androidx.ui.input.TextInputService textInputService;
property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
- field public static final androidx.ui.core.Owner.Companion! Companion;
+ field public static final androidx.ui.core.Owner.Companion Companion;
}
public static final class Owner.Companion {
@@ -736,6 +735,8 @@
}
public enum PointerEventPass {
+ method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.PointerEventPass[] values();
enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -815,7 +816,6 @@
}
public final class TestTagKt {
- method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
}
@@ -828,7 +828,7 @@
method public static float getPivotFractionY-impl(long $this);
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method @androidx.compose.Immutable public static inline String! toString-impl(long p);
- field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+ field public static final androidx.ui.core.TransformOrigin.Companion Companion;
}
public static final class TransformOrigin.Companion {
@@ -861,8 +861,8 @@
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
}
public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -891,6 +891,8 @@
package androidx.ui.core.focus {
public enum FocusDetailedState {
+ method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusDetailedState[] values();
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -915,6 +917,8 @@
}
public enum FocusState {
+ method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusState[] values();
enum_constant public static final androidx.ui.core.focus.FocusState Focused;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -964,7 +968,10 @@
}
public final class DragSlopExceededGestureFilterKt {
- method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+ method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+ }
+
+ @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
}
public final class GestureUtilsKt {
@@ -992,7 +999,7 @@
}
public final class RawDragGestureFilterKt {
- method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+ method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
}
public final class RawPressStartGestureFilterKt {
@@ -1028,6 +1035,17 @@
public final class ScaleUtilKt {
}
+ public interface ScrollCallback {
+ method public default void onCancel();
+ method public default float onScroll(float scrollDistance);
+ method public default void onStart(androidx.ui.geometry.Offset downPosition);
+ method public default void onStop(float velocity);
+ }
+
+ public final class ScrollGestureFilterKt {
+ method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+ }
+
public final class TapGestureFilterKt {
method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
}
@@ -1047,13 +1065,36 @@
}
public enum DelayUpMessage {
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
}
public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
- field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+ field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+ }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+ public enum Orientation {
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+ }
+
+ @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+ ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+ method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public void onCancel();
+ method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
}
}
@@ -1082,6 +1123,8 @@
}
public enum HapticFeedbackType {
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
}
@@ -1115,7 +1158,7 @@
method public int getKeyCode();
method public static inline int hashCode-impl(int p);
method public static String toString-impl(int $this);
- field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+ field public static final androidx.ui.core.keyinput.Key.Companion Companion;
}
public static final class Key.Companion {
@@ -1708,6 +1751,8 @@
}
public enum KeyEventType {
+ method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.keyinput.KeyEventType[] values();
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
}
@@ -1791,6 +1836,9 @@
public final class SelectionHandlesKt {
}
+ public final class SelectionLayoutKt {
+ }
+
public final class SelectionManagerKt {
}
@@ -1840,19 +1888,18 @@
}
public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
- method public boolean getApplyToChildLayoutNode();
method public int getId();
method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
- property public abstract boolean applyToChildLayoutNode;
property public abstract int id;
property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
}
public final class SemanticsModifierKt {
- method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+ method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
}
public final class SemanticsNode {
+ method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
method public androidx.ui.unit.PxBounds getBoundsInRoot();
method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1875,7 +1922,7 @@
property public final boolean isRoot;
property public final androidx.ui.core.semantics.SemanticsNode? parent;
property public final androidx.ui.unit.IntSize size;
- field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+ field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
}
public static final class SemanticsNode.Companion {
@@ -1909,6 +1956,8 @@
}
public enum TextToolbarStatus {
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
}
@@ -1929,6 +1978,13 @@
method public final void invalidate();
}
+ public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+ ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+ method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ }
+
public final class VectorAsset {
method public String component1();
method public float component2();
@@ -1963,8 +2019,8 @@
}
public final class VectorComposeKt {
- method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
- method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+ method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
}
public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2017,7 +2073,7 @@
public final class VectorPainterKt {
method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
- method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+ method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
field public static final String RootGroupName = "VectorRootGroup";
}
@@ -2046,9 +2102,6 @@
method public float getStrokeLineWidth();
}
- public final class VectorScope {
- }
-
}
package androidx.ui.graphics.vector.compat {
@@ -2076,17 +2129,16 @@
public final class PointerInteropUtilsKt {
}
- public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
- ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
- method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public android.content.Context getContext();
- method public Object getRoot();
- }
-
- public final class UiComposerKt {
+ public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+ ctor public UiApplier(Object root);
+ method public void down(Object node);
+ method public Object getCurrent();
+ method public void insert(int index, Object instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ method public void reset();
+ method public void up();
+ property public Object current;
}
public final class ViewInteropKt {
@@ -2211,11 +2263,7 @@
property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
- field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
- }
-
- public final class SemanticsKt {
- method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
}
public final class SemanticsProperties {
@@ -2235,7 +2283,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
- field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+ field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
}
public final class SemanticsPropertiesKt {
@@ -2331,6 +2379,11 @@
method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
}
+ public final class EmitViewKt {
+ method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+ method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ }
+
}
package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/restricted_0.1.0-dev15.txt b/ui/ui-core/api/restricted_0.1.0-dev15.txt
index 2f45773..97e1ad4d 100644
--- a/ui/ui-core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-core/api/restricted_0.1.0-dev15.txt
@@ -1,12 +1,4 @@
// Signature format: 3.0
-package androidx.compose {
-
- public final class ComposerCompatKt {
- method @Deprecated public static androidx.ui.node.UiComposer getComposer();
- }
-
-}
-
package androidx.ui.autofill {
public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
}
public enum AutofillType {
+ method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.autofill.AutofillType[] values();
enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
@androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
- field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+ field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
}
public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
@androidx.compose.Immutable public interface Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
- field public static final androidx.ui.core.Alignment.Companion! Companion;
+ field public static final androidx.ui.core.Alignment.Companion Companion;
}
public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
}
@androidx.compose.Immutable public abstract sealed class AlignmentLine {
- field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+ field public static final androidx.ui.core.AlignmentLine.Companion Companion;
field public static final int Unspecified = -2147483648; // 0x80000000
}
@@ -262,7 +256,7 @@
@androidx.compose.Stable public interface ContentScale {
method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
- field public static final androidx.ui.core.ContentScale.Companion! Companion;
+ field public static final androidx.ui.core.ContentScale.Companion Companion;
}
public static final class ContentScale.Companion {
@@ -311,6 +305,8 @@
}
public enum Direction {
+ method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.Direction[] values();
enum_constant public static final androidx.ui.core.Direction DOWN;
enum_constant public static final androidx.ui.core.Direction LEFT;
enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -363,6 +359,8 @@
}
public enum DropDownAlignment {
+ method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.DropDownAlignment[] values();
enum_constant public static final androidx.ui.core.DropDownAlignment End;
enum_constant public static final androidx.ui.core.DropDownAlignment Start;
}
@@ -402,11 +400,15 @@
}
@kotlin.PublishedApi internal enum IntrinsicMinMax {
+ method public static androidx.ui.core.IntrinsicMinMax valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.IntrinsicMinMax[] values();
enum_constant public static final androidx.ui.core.IntrinsicMinMax Max;
enum_constant public static final androidx.ui.core.IntrinsicMinMax Min;
}
@kotlin.PublishedApi internal enum IntrinsicWidthHeight {
+ method public static androidx.ui.core.IntrinsicWidthHeight valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.IntrinsicWidthHeight[] values();
enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Height;
enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Width;
}
@@ -472,7 +474,6 @@
method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
- method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
}
@@ -494,7 +495,6 @@
method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
method public androidx.ui.core.LayoutCoordinates getCoordinates();
method public int getDepth();
- method @Deprecated public boolean getHandlesParentData();
method public int getHeight();
method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -525,7 +525,6 @@
method public void requestRemeasure();
method @Deprecated public void setCanMultiMeasure(boolean p);
method public void setDepth(int p);
- method @Deprecated public void setHandlesParentData(boolean p);
method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
method public void setModifier(androidx.ui.core.Modifier value);
method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
@@ -535,7 +534,6 @@
property public final java.util.List<androidx.ui.core.LayoutNode> children;
property public final androidx.ui.core.LayoutCoordinates coordinates;
property public final int depth;
- property @Deprecated public final boolean handlesParentData;
property public final int height;
property public final boolean isPlaced;
property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -552,6 +550,8 @@
}
public enum LayoutNode.LayoutState {
+ method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutNode.LayoutState[] values();
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
@@ -635,7 +635,7 @@
method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
- field public static final androidx.ui.core.Modifier.Companion! Companion;
+ field public static final androidx.ui.core.Modifier.Companion Companion;
}
public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -685,12 +685,15 @@
method public void drawLayer(androidx.ui.graphics.Canvas canvas);
method public long getLayerId();
method public android.graphics.Matrix getMatrix();
+ method public androidx.ui.core.DrawLayerModifier getModifier();
method public void invalidate();
method public void move(androidx.ui.unit.IntOffset position);
method public void resize(androidx.ui.unit.IntSize size);
+ method public void setModifier(androidx.ui.core.DrawLayerModifier p);
method public void updateDisplayList();
method public void updateLayerProperties();
property public abstract long layerId;
+ property public abstract androidx.ui.core.DrawLayerModifier modifier;
}
public interface Owner {
@@ -736,7 +739,7 @@
property public abstract boolean showLayoutBounds;
property public abstract androidx.ui.input.TextInputService textInputService;
property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
- field public static final androidx.ui.core.Owner.Companion! Companion;
+ field public static final androidx.ui.core.Owner.Companion Companion;
}
public static final class Owner.Companion {
@@ -786,6 +789,8 @@
}
public enum PointerEventPass {
+ method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.PointerEventPass[] values();
enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -865,7 +870,6 @@
}
public final class TestTagKt {
- method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
}
@@ -878,7 +882,7 @@
method public static float getPivotFractionY-impl(long $this);
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method @androidx.compose.Immutable public static inline String! toString-impl(long p);
- field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+ field public static final androidx.ui.core.TransformOrigin.Companion Companion;
}
public static final class TransformOrigin.Companion {
@@ -911,8 +915,8 @@
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
}
public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -941,6 +945,8 @@
package androidx.ui.core.focus {
public enum FocusDetailedState {
+ method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusDetailedState[] values();
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -965,6 +971,8 @@
}
public enum FocusState {
+ method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusState[] values();
enum_constant public static final androidx.ui.core.focus.FocusState Focused;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -1014,7 +1022,10 @@
}
public final class DragSlopExceededGestureFilterKt {
- method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+ method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+ }
+
+ @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
}
public final class GestureUtilsKt {
@@ -1042,7 +1053,7 @@
}
public final class RawDragGestureFilterKt {
- method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+ method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
}
public final class RawPressStartGestureFilterKt {
@@ -1078,6 +1089,17 @@
public final class ScaleUtilKt {
}
+ public interface ScrollCallback {
+ method public default void onCancel();
+ method public default float onScroll(float scrollDistance);
+ method public default void onStart(androidx.ui.geometry.Offset downPosition);
+ method public default void onStop(float velocity);
+ }
+
+ public final class ScrollGestureFilterKt {
+ method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+ }
+
public final class TapGestureFilterKt {
method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
}
@@ -1097,13 +1119,36 @@
}
public enum DelayUpMessage {
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
}
public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
- field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+ field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+ }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+ public enum Orientation {
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+ }
+
+ @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+ ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+ method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public void onCancel();
+ method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
}
}
@@ -1132,6 +1177,8 @@
}
public enum HapticFeedbackType {
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
}
@@ -1165,7 +1212,7 @@
method public int getKeyCode();
method public static inline int hashCode-impl(int p);
method public static String toString-impl(int $this);
- field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+ field public static final androidx.ui.core.keyinput.Key.Companion Companion;
}
public static final class Key.Companion {
@@ -1758,6 +1805,8 @@
}
public enum KeyEventType {
+ method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.keyinput.KeyEventType[] values();
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
}
@@ -1841,6 +1890,9 @@
public final class SelectionHandlesKt {
}
+ public final class SelectionLayoutKt {
+ }
+
public final class SelectionManagerKt {
}
@@ -1890,19 +1942,18 @@
}
public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
- method public boolean getApplyToChildLayoutNode();
method public int getId();
method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
- property public abstract boolean applyToChildLayoutNode;
property public abstract int id;
property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
}
public final class SemanticsModifierKt {
- method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+ method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
}
public final class SemanticsNode {
+ method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
method public androidx.ui.unit.PxBounds getBoundsInRoot();
method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1925,7 +1976,7 @@
property public final boolean isRoot;
property public final androidx.ui.core.semantics.SemanticsNode? parent;
property public final androidx.ui.unit.IntSize size;
- field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+ field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
}
public static final class SemanticsNode.Companion {
@@ -1959,6 +2010,8 @@
}
public enum TextToolbarStatus {
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
}
@@ -1979,6 +2032,13 @@
method public final void invalidate();
}
+ public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+ ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+ method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ }
+
public final class VectorAsset {
method public String component1();
method public float component2();
@@ -2013,8 +2073,8 @@
}
public final class VectorComposeKt {
- method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
- method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+ method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
}
public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2067,7 +2127,7 @@
public final class VectorPainterKt {
method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
- method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+ method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
field public static final String RootGroupName = "VectorRootGroup";
}
@@ -2096,9 +2156,6 @@
method public float getStrokeLineWidth();
}
- public final class VectorScope {
- }
-
}
package androidx.ui.graphics.vector.compat {
@@ -2126,17 +2183,16 @@
public final class PointerInteropUtilsKt {
}
- public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
- ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
- method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public android.content.Context getContext();
- method public Object getRoot();
- }
-
- public final class UiComposerKt {
+ public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+ ctor public UiApplier(Object root);
+ method public void down(Object node);
+ method public Object getCurrent();
+ method public void insert(int index, Object instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ method public void reset();
+ method public void up();
+ property public Object current;
}
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public interface ViewAdapter {
@@ -2270,11 +2326,7 @@
property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
- field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
- }
-
- public final class SemanticsKt {
- method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
}
public final class SemanticsProperties {
@@ -2294,7 +2346,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
- field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+ field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
}
public final class SemanticsPropertiesKt {
@@ -2390,6 +2442,11 @@
method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
}
+ public final class EmitViewKt {
+ method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+ method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ }
+
}
package androidx.ui.viewmodel {
diff --git a/ui/ui-core/api/restricted_current.txt b/ui/ui-core/api/restricted_current.txt
index 2f45773..97e1ad4d 100644
--- a/ui/ui-core/api/restricted_current.txt
+++ b/ui/ui-core/api/restricted_current.txt
@@ -1,12 +1,4 @@
// Signature format: 3.0
-package androidx.compose {
-
- public final class ComposerCompatKt {
- method @Deprecated public static androidx.ui.node.UiComposer getComposer();
- }
-
-}
-
package androidx.ui.autofill {
public final class AndroidAutofillDebugUtilsKt {
@@ -46,6 +38,8 @@
}
public enum AutofillType {
+ method public static androidx.ui.autofill.AutofillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.autofill.AutofillType[] values();
enum_constant public static final androidx.ui.autofill.AutofillType AddressAuxiliaryDetails;
enum_constant public static final androidx.ui.autofill.AutofillType AddressCountry;
enum_constant public static final androidx.ui.autofill.AutofillType AddressLocality;
@@ -92,7 +86,7 @@
@androidx.compose.Immutable public final class AbsoluteAlignment implements androidx.ui.core.Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection);
method @androidx.compose.Immutable public androidx.ui.core.AbsoluteAlignment copy(float verticalBias, float horizontalBias);
- field public static final androidx.ui.core.AbsoluteAlignment.Companion! Companion;
+ field public static final androidx.ui.core.AbsoluteAlignment.Companion Companion;
}
public static final class AbsoluteAlignment.Companion {
@@ -121,7 +115,7 @@
@androidx.compose.Immutable public interface Alignment {
method public androidx.ui.unit.IntOffset align(androidx.ui.unit.IntSize size, androidx.ui.core.LayoutDirection layoutDirection = LayoutDirection.Ltr);
- field public static final androidx.ui.core.Alignment.Companion! Companion;
+ field public static final androidx.ui.core.Alignment.Companion Companion;
}
public static final class Alignment.Companion {
@@ -166,7 +160,7 @@
}
@androidx.compose.Immutable public abstract sealed class AlignmentLine {
- field public static final androidx.ui.core.AlignmentLine.Companion! Companion;
+ field public static final androidx.ui.core.AlignmentLine.Companion Companion;
field public static final int Unspecified = -2147483648; // 0x80000000
}
@@ -262,7 +256,7 @@
@androidx.compose.Stable public interface ContentScale {
method public float scale(androidx.ui.geometry.Size srcSize, androidx.ui.geometry.Size dstSize);
- field public static final androidx.ui.core.ContentScale.Companion! Companion;
+ field public static final androidx.ui.core.ContentScale.Companion Companion;
}
public static final class ContentScale.Companion {
@@ -311,6 +305,8 @@
}
public enum Direction {
+ method public static androidx.ui.core.Direction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.Direction[] values();
enum_constant public static final androidx.ui.core.Direction DOWN;
enum_constant public static final androidx.ui.core.Direction LEFT;
enum_constant public static final androidx.ui.core.Direction RIGHT;
@@ -363,6 +359,8 @@
}
public enum DropDownAlignment {
+ method public static androidx.ui.core.DropDownAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.DropDownAlignment[] values();
enum_constant public static final androidx.ui.core.DropDownAlignment End;
enum_constant public static final androidx.ui.core.DropDownAlignment Start;
}
@@ -402,11 +400,15 @@
}
@kotlin.PublishedApi internal enum IntrinsicMinMax {
+ method public static androidx.ui.core.IntrinsicMinMax valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.IntrinsicMinMax[] values();
enum_constant public static final androidx.ui.core.IntrinsicMinMax Max;
enum_constant public static final androidx.ui.core.IntrinsicMinMax Min;
}
@kotlin.PublishedApi internal enum IntrinsicWidthHeight {
+ method public static androidx.ui.core.IntrinsicWidthHeight valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.IntrinsicWidthHeight[] values();
enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Height;
enum_constant public static final androidx.ui.core.IntrinsicWidthHeight Width;
}
@@ -472,7 +474,6 @@
method @androidx.compose.Composable public static void Layout(kotlin.jvm.functions.Function0<kotlin.Unit> children, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method public static androidx.ui.core.LayoutNode.MeasureBlocks MeasuringIntrinsicsMeasureBlocks(kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
method @Deprecated @androidx.compose.Composable public static void MultiMeasureLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children, kotlin.jvm.functions.Function4<? super androidx.ui.core.MeasureScope,? super java.util.List<? extends androidx.ui.core.Measurable>,? super androidx.ui.core.Constraints,? super androidx.ui.core.LayoutDirection,? extends androidx.ui.core.MeasureScope.MeasureResult> measureBlock);
- method @Deprecated @androidx.compose.Composable public static void PassThroughLayout(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static void WithConstraints(androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.WithConstraintsScope,kotlin.Unit> children);
}
@@ -494,7 +495,6 @@
method public java.util.List<androidx.ui.core.LayoutNode> getChildren();
method public androidx.ui.core.LayoutCoordinates getCoordinates();
method public int getDepth();
- method @Deprecated public boolean getHandlesParentData();
method public int getHeight();
method public androidx.ui.core.LayoutNode.LayoutState getLayoutState();
method public androidx.ui.core.LayoutNode.MeasureBlocks getMeasureBlocks();
@@ -525,7 +525,6 @@
method public void requestRemeasure();
method @Deprecated public void setCanMultiMeasure(boolean p);
method public void setDepth(int p);
- method @Deprecated public void setHandlesParentData(boolean p);
method public void setMeasureBlocks(androidx.ui.core.LayoutNode.MeasureBlocks value);
method public void setModifier(androidx.ui.core.Modifier value);
method public void setOnAttach(kotlin.jvm.functions.Function1<? super androidx.ui.core.Owner,kotlin.Unit>? p);
@@ -535,7 +534,6 @@
property public final java.util.List<androidx.ui.core.LayoutNode> children;
property public final androidx.ui.core.LayoutCoordinates coordinates;
property public final int depth;
- property @Deprecated public final boolean handlesParentData;
property public final int height;
property public final boolean isPlaced;
property public final androidx.ui.core.LayoutNode.LayoutState layoutState;
@@ -552,6 +550,8 @@
}
public enum LayoutNode.LayoutState {
+ method public static androidx.ui.core.LayoutNode.LayoutState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutNode.LayoutState[] values();
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState LayingOut;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState Measuring;
enum_constant public static final androidx.ui.core.LayoutNode.LayoutState NeedsRelayout;
@@ -635,7 +635,7 @@
method public <R> R! foldIn(R? initial, kotlin.jvm.functions.Function2<? super R,? super androidx.ui.core.Modifier.Element,? extends R> operation);
method public <R> R! foldOut(R? initial, kotlin.jvm.functions.Function2<? super androidx.ui.core.Modifier.Element,? super R,? extends R> operation);
method public default operator androidx.ui.core.Modifier plus(androidx.ui.core.Modifier other);
- field public static final androidx.ui.core.Modifier.Companion! Companion;
+ field public static final androidx.ui.core.Modifier.Companion Companion;
}
public static final class Modifier.Companion implements androidx.ui.core.Modifier {
@@ -685,12 +685,15 @@
method public void drawLayer(androidx.ui.graphics.Canvas canvas);
method public long getLayerId();
method public android.graphics.Matrix getMatrix();
+ method public androidx.ui.core.DrawLayerModifier getModifier();
method public void invalidate();
method public void move(androidx.ui.unit.IntOffset position);
method public void resize(androidx.ui.unit.IntSize size);
+ method public void setModifier(androidx.ui.core.DrawLayerModifier p);
method public void updateDisplayList();
method public void updateLayerProperties();
property public abstract long layerId;
+ property public abstract androidx.ui.core.DrawLayerModifier modifier;
}
public interface Owner {
@@ -736,7 +739,7 @@
property public abstract boolean showLayoutBounds;
property public abstract androidx.ui.input.TextInputService textInputService;
property public abstract androidx.ui.core.texttoolbar.TextToolbar textToolbar;
- field public static final androidx.ui.core.Owner.Companion! Companion;
+ field public static final androidx.ui.core.Owner.Companion Companion;
}
public static final class Owner.Companion {
@@ -786,6 +789,8 @@
}
public enum PointerEventPass {
+ method public static androidx.ui.core.PointerEventPass valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.PointerEventPass[] values();
enum_constant public static final androidx.ui.core.PointerEventPass InitialDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostDown;
enum_constant public static final androidx.ui.core.PointerEventPass PostUp;
@@ -865,7 +870,6 @@
}
public final class TestTagKt {
- method @Deprecated @androidx.compose.Composable public static void TestTag(String tag, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Stable public static androidx.ui.core.Modifier testTag(androidx.ui.core.Modifier, String tag);
}
@@ -878,7 +882,7 @@
method public static float getPivotFractionY-impl(long $this);
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method @androidx.compose.Immutable public static inline String! toString-impl(long p);
- field public static final androidx.ui.core.TransformOrigin.Companion! Companion;
+ field public static final androidx.ui.core.TransformOrigin.Companion Companion;
}
public static final class TransformOrigin.Companion {
@@ -911,8 +915,8 @@
method @Deprecated public static androidx.compose.Composition setContent(android.view.ViewGroup, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method public static androidx.compose.Composition setViewContent(android.view.ViewGroup, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
method public static androidx.compose.Composition setViewContent(android.app.Activity, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @MainThread public static androidx.compose.Composition subcomposeInto(android.content.Context context, androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
- method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, android.content.Context context, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.Recomposer recomposer, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+ method @Deprecated @MainThread public static androidx.compose.Composition subcomposeInto(androidx.ui.core.LayoutNode container, androidx.compose.CompositionReference? parent = null, kotlin.jvm.functions.Function0<kotlin.Unit> composable);
}
public interface ZIndexModifier extends androidx.ui.core.Modifier.Element {
@@ -941,6 +945,8 @@
package androidx.ui.core.focus {
public enum FocusDetailedState {
+ method public static androidx.ui.core.focus.FocusDetailedState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusDetailedState[] values();
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Active;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState ActiveParent;
enum_constant public static final androidx.ui.core.focus.FocusDetailedState Captured;
@@ -965,6 +971,8 @@
}
public enum FocusState {
+ method public static androidx.ui.core.focus.FocusState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.focus.FocusState[] values();
enum_constant public static final androidx.ui.core.focus.FocusState Focused;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocusable;
enum_constant public static final androidx.ui.core.focus.FocusState NotFocused;
@@ -1014,7 +1022,10 @@
}
public final class DragSlopExceededGestureFilterKt {
- method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null);
+ method public static androidx.ui.core.Modifier dragSlopExceededGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> onDragSlopExceeded, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
+ }
+
+ @kotlin.RequiresOptIn(message="This pointer input API is experimental and is likely to change before becoming " + "stable.") public @interface ExperimentalPointerInput {
}
public final class GestureUtilsKt {
@@ -1042,7 +1053,7 @@
}
public final class RawDragGestureFilterKt {
- method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null);
+ method public static androidx.ui.core.Modifier rawDragGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.DragObserver dragObserver, kotlin.jvm.functions.Function0<java.lang.Boolean>? canStartDragging = null, androidx.ui.core.gesture.scrollorientationlocking.Orientation? orientation = null);
}
public final class RawPressStartGestureFilterKt {
@@ -1078,6 +1089,17 @@
public final class ScaleUtilKt {
}
+ public interface ScrollCallback {
+ method public default void onCancel();
+ method public default float onScroll(float scrollDistance);
+ method public default void onStart(androidx.ui.geometry.Offset downPosition);
+ method public default void onStop(float velocity);
+ }
+
+ public final class ScrollGestureFilterKt {
+ method public static androidx.ui.core.Modifier scrollGestureFilter(androidx.ui.core.Modifier, androidx.ui.core.gesture.ScrollCallback scrollCallback, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation, kotlin.jvm.functions.Function1<? super androidx.ui.core.Direction,java.lang.Boolean>? canDrag = null, boolean startDragImmediately = false);
+ }
+
public final class TapGestureFilterKt {
method public static androidx.ui.core.Modifier tapGestureFilter(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.geometry.Offset,kotlin.Unit> onTap);
}
@@ -1097,13 +1119,36 @@
}
public enum DelayUpMessage {
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.customevents.DelayUpMessage[] values();
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayUp;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpConsumed;
enum_constant public static final androidx.ui.core.gesture.customevents.DelayUpMessage DelayedUpNotConsumed;
}
public final class LongPressFiredEvent implements androidx.ui.core.CustomEvent {
- field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent! INSTANCE;
+ field public static final androidx.ui.core.gesture.customevents.LongPressFiredEvent INSTANCE;
+ }
+
+}
+
+package androidx.ui.core.gesture.scrollorientationlocking {
+
+ public enum Orientation {
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.gesture.scrollorientationlocking.Orientation[] values();
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Horizontal;
+ enum_constant public static final androidx.ui.core.gesture.scrollorientationlocking.Orientation Vertical;
+ }
+
+ @androidx.ui.core.gesture.ExperimentalPointerInput public final class ScrollOrientationLocker {
+ ctor public ScrollOrientationLocker(androidx.ui.core.CustomEventDispatcher customEventDispatcher);
+ method public void attemptToLockPointers(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public java.util.List<androidx.ui.core.PointerInputChange> getPointersFor(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.gesture.scrollorientationlocking.Orientation orientation);
+ method public void onCancel();
+ method public void onCustomEvent(androidx.ui.core.CustomEvent customEvent, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputSetup(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
+ method public void onPointerInputTearDown(java.util.List<androidx.ui.core.PointerInputChange> changes, androidx.ui.core.PointerEventPass pass);
}
}
@@ -1132,6 +1177,8 @@
}
public enum HapticFeedbackType {
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.hapticfeedback.HapticFeedbackType[] values();
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType LongPress;
enum_constant public static final androidx.ui.core.hapticfeedback.HapticFeedbackType TextHandleMove;
}
@@ -1165,7 +1212,7 @@
method public int getKeyCode();
method public static inline int hashCode-impl(int p);
method public static String toString-impl(int $this);
- field public static final androidx.ui.core.keyinput.Key.Companion! Companion;
+ field public static final androidx.ui.core.keyinput.Key.Companion Companion;
}
public static final class Key.Companion {
@@ -1758,6 +1805,8 @@
}
public enum KeyEventType {
+ method public static androidx.ui.core.keyinput.KeyEventType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.keyinput.KeyEventType[] values();
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyDown;
enum_constant public static final androidx.ui.core.keyinput.KeyEventType KeyUp;
}
@@ -1841,6 +1890,9 @@
public final class SelectionHandlesKt {
}
+ public final class SelectionLayoutKt {
+ }
+
public final class SelectionManagerKt {
}
@@ -1890,19 +1942,18 @@
}
public interface SemanticsModifier extends androidx.ui.core.Modifier.Element {
- method public boolean getApplyToChildLayoutNode();
method public int getId();
method public androidx.ui.core.semantics.SemanticsConfiguration getSemanticsConfiguration();
- property public abstract boolean applyToChildLayoutNode;
property public abstract int id;
property public abstract androidx.ui.core.semantics.SemanticsConfiguration semanticsConfiguration;
}
public final class SemanticsModifierKt {
- method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean applyToChildLayoutNode = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
+ method public static androidx.ui.core.Modifier semantics(androidx.ui.core.Modifier, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null);
}
public final class SemanticsNode {
+ method public int getAlignmentLinePosition(androidx.ui.core.AlignmentLine line);
method public androidx.ui.unit.PxBounds getBoundsInRoot();
method public java.util.List<androidx.ui.core.semantics.SemanticsNode> getChildren();
method public androidx.ui.core.LayoutNode getComponentNode();
@@ -1925,7 +1976,7 @@
property public final boolean isRoot;
property public final androidx.ui.core.semantics.SemanticsNode? parent;
property public final androidx.ui.unit.IntSize size;
- field public static final androidx.ui.core.semantics.SemanticsNode.Companion! Companion;
+ field public static final androidx.ui.core.semantics.SemanticsNode.Companion Companion;
}
public static final class SemanticsNode.Companion {
@@ -1959,6 +2010,8 @@
}
public enum TextToolbarStatus {
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.texttoolbar.TextToolbarStatus[] values();
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Hidden;
enum_constant public static final androidx.ui.core.texttoolbar.TextToolbarStatus Shown;
}
@@ -1979,6 +2032,13 @@
method public final void invalidate();
}
+ public final class VectorApplier extends androidx.compose.AbstractApplier<androidx.ui.graphics.vector.VNode> {
+ ctor public VectorApplier(androidx.ui.graphics.vector.VNode root);
+ method public void insert(int index, androidx.ui.graphics.vector.VNode instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ }
+
public final class VectorAsset {
method public String component1();
method public float component2();
@@ -2013,8 +2073,8 @@
}
public final class VectorComposeKt {
- method @androidx.compose.Composable public static void Group(androidx.ui.graphics.vector.VectorScope, String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorScope,kotlin.Unit> children);
- method @androidx.compose.Composable public static void Path(androidx.ui.graphics.vector.VectorScope, java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
+ method @androidx.compose.Composable public static void Group(String name = "", float rotation = 0.0f, float pivotX = 0.0f, float pivotY = 0.0f, float scaleX = 1.0f, float scaleY = 1.0f, float translationX = 0.0f, float translationY = 0.0f, java.util.List<? extends androidx.ui.graphics.vector.PathNode> clipPathData = EmptyPath, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method @androidx.compose.Composable public static void Path(java.util.List<? extends androidx.ui.graphics.vector.PathNode> pathData, String name = "", androidx.ui.graphics.Brush? fill = null, float fillAlpha = 1.0f, androidx.ui.graphics.Brush? stroke = null, float strokeAlpha = 1.0f, float strokeLineWidth = 0.0f, androidx.ui.graphics.StrokeCap strokeLineCap = DefaultStrokeLineCap, androidx.ui.graphics.StrokeJoin strokeLineJoin = DefaultStrokeLineJoin, float strokeLineMiter = 4.0f);
}
public final class VectorGroup extends androidx.ui.graphics.vector.VectorNode implements java.lang.Iterable<androidx.ui.graphics.vector.VectorNode> kotlin.jvm.internal.markers.KMappedMarker {
@@ -2067,7 +2127,7 @@
public final class VectorPainterKt {
method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter(androidx.ui.graphics.vector.VectorAsset asset);
- method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-uAXuNKI(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function3<? super androidx.ui.graphics.vector.VectorScope,? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
+ method @androidx.compose.Composable public static androidx.ui.graphics.vector.VectorPainter VectorPainter-CZQlTzY(float defaultWidth, float defaultHeight, float viewportWidth = Float.NaN, float viewportHeight = Float.NaN, String name = "VectorRootGroup", kotlin.jvm.functions.Function2<? super java.lang.Float,? super java.lang.Float,kotlin.Unit> children);
field public static final String RootGroupName = "VectorRootGroup";
}
@@ -2096,9 +2156,6 @@
method public float getStrokeLineWidth();
}
- public final class VectorScope {
- }
-
}
package androidx.ui.graphics.vector.compat {
@@ -2126,17 +2183,16 @@
public final class PointerInteropUtilsKt {
}
- public final class UiComposer extends androidx.compose.Composer<java.lang.Object> {
- ctor public UiComposer(android.content.Context context, Object root, androidx.compose.SlotTable slotTable, androidx.compose.Recomposer recomposer);
- method public inline <T extends android.view.View> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends android.view.ViewGroup> void emit(Object key, kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update);
- method public inline <T extends androidx.ui.core.LayoutNode> void emit(Object key, kotlin.jvm.functions.Function0<? extends T> ctor, kotlin.jvm.functions.Function1<? super androidx.compose.ComposerUpdater<java.lang.Object,T>,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
- method public android.content.Context getContext();
- method public Object getRoot();
- }
-
- public final class UiComposerKt {
+ public final class UiApplier implements androidx.compose.Applier<java.lang.Object> {
+ ctor public UiApplier(Object root);
+ method public void down(Object node);
+ method public Object getCurrent();
+ method public void insert(int index, Object instance);
+ method public void move(int from, int to, int count);
+ method public void remove(int index, int count);
+ method public void reset();
+ method public void up();
+ property public Object current;
}
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public interface ViewAdapter {
@@ -2270,11 +2326,7 @@
property @Deprecated public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function0<java.lang.Boolean>>> ScrollForward;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function2<java.lang.Float,java.lang.Float,java.lang.Boolean>>> ScrollTo;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.semantics.AccessibilityAction<kotlin.jvm.functions.Function1<java.lang.Float,java.lang.Boolean>>> SetProgress;
- field public static final androidx.ui.semantics.SemanticsActions! INSTANCE;
- }
-
- public final class SemanticsKt {
- method @Deprecated @androidx.compose.Composable public static void Semantics(boolean container = false, boolean mergeAllDescendants = false, kotlin.jvm.functions.Function1<? super androidx.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>? properties = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ field public static final androidx.ui.semantics.SemanticsActions INSTANCE;
}
public final class SemanticsProperties {
@@ -2294,7 +2346,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsPopup;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.String> TestTag;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.text.AnnotatedString> Text;
- field public static final androidx.ui.semantics.SemanticsProperties! INSTANCE;
+ field public static final androidx.ui.semantics.SemanticsProperties INSTANCE;
}
public final class SemanticsPropertiesKt {
@@ -2390,6 +2442,11 @@
method @androidx.compose.Composable public static void AndroidView(android.view.View view, androidx.ui.core.Modifier modifier = Modifier);
}
+ public final class EmitViewKt {
+ method @androidx.compose.Composable public static <T extends android.view.View> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update);
+ method @androidx.compose.Composable public static <T extends android.view.ViewGroup> void emitView(kotlin.jvm.functions.Function1<? super android.content.Context,? extends T> ctor, kotlin.jvm.functions.Function1<? super T,kotlin.Unit> update, kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ }
+
}
package androidx.ui.viewmodel {
diff --git a/ui/ui-core/build.gradle b/ui/ui-core/build.gradle
index a936d8d..67d44ad 100644
--- a/ui/ui-core/build.gradle
+++ b/ui/ui-core/build.gradle
@@ -124,7 +124,9 @@
testOptions.unitTests.includeAndroidResources = true
}
-// An ugly hack to workaround bug in MPP Kotlin Gradle plugin.
+// An ugly hack to workaround b/159426957 causing MPP+AGP to conflict.
+// See also: https://youtrack.jetbrains.com/issue/KT-34650
+// See also: https://youtrack.jetbrains.com/issue/KT-39712
afterEvaluate {
["Api", "Implementation", "CompileOnly", "RuntimeOnly"].each { scope ->
def erroneousExtendsFrom = [
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
index 3fbfa70..6420041 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
@@ -20,21 +20,23 @@
import androidx.ui.core.demos.focus.FocusableDemo
import androidx.ui.core.demos.gestures.DoubleTapGestureFilterDemo
import androidx.ui.core.demos.gestures.DoubleTapInTapDemo
-import androidx.ui.core.demos.gestures.DragAndScaleGestureDetectorDemo
+import androidx.ui.core.demos.gestures.DragAndScaleGestureFilterDemo
+import androidx.ui.core.demos.gestures.DragGestureFilterDemo
import androidx.ui.core.demos.gestures.DragSlopExceededGestureFilterDemo
-import androidx.ui.core.demos.gestures.LongPressGestureDetectorDemo
+import androidx.ui.core.demos.gestures.HorizontalScrollersInVerticalScrollersDemo
+import androidx.ui.core.demos.gestures.LongPressDragGestureFilterDemo
import androidx.ui.core.demos.gestures.NestedLongPressDemo
import androidx.ui.core.demos.gestures.NestedPressingDemo
import androidx.ui.core.demos.gestures.NestedScalingDemo
import androidx.ui.core.demos.gestures.NestedScrollingDemo
import androidx.ui.core.demos.gestures.PopupDragDemo
import androidx.ui.core.demos.gestures.PressIndicatorGestureFilterDemo
-import androidx.ui.core.demos.gestures.TapGestureFilterDemo
import androidx.ui.core.demos.gestures.RawDragGestureFilterDemo
import androidx.ui.core.demos.gestures.ScaleGestureFilterDemo
-import androidx.ui.core.demos.gestures.DragGestureFilterDemo
-import androidx.ui.core.demos.gestures.LongPressDragGestureFilterDemo
import androidx.ui.core.demos.gestures.PointerInputDuringSubComp
+import androidx.ui.core.demos.gestures.ScrollGestureFilterDemo
+import androidx.ui.core.demos.gestures.TapGestureFilterDemo
+import androidx.ui.core.demos.gestures.VerticalScrollerInDrawerDemo
import androidx.ui.core.demos.keyinput.KeyInputDemo
import androidx.ui.core.demos.viewinterop.ViewInComposeDemo
import androidx.ui.demos.common.ComposableDemo
@@ -45,7 +47,8 @@
ComposableDemo("Press Indication") { PressIndicatorGestureFilterDemo() },
ComposableDemo("Tap") { TapGestureFilterDemo() },
ComposableDemo("Double Tap") { DoubleTapGestureFilterDemo() },
- ComposableDemo("Long Press") { LongPressGestureDetectorDemo() },
+ ComposableDemo("Long Press") { ScrollGestureFilterDemo() },
+ ComposableDemo("Scroll") { DragGestureFilterDemo() },
ComposableDemo("Drag") { DragGestureFilterDemo() },
ComposableDemo("Long Press Drag") { LongPressDragGestureFilterDemo() },
ComposableDemo("Scale") { ScaleGestureFilterDemo() }
@@ -57,9 +60,15 @@
DemoCategory(
"Combinations / Case Studies", listOf(
ComposableDemo("Nested Pressing") { NestedPressingDemo() },
+ ComposableDemo("Horizontal Scrollers In Vertical Scroller") {
+ HorizontalScrollersInVerticalScrollersDemo()
+ },
+ ComposableDemo("Vertical Scroller in Nav Drawer") {
+ VerticalScrollerInDrawerDemo()
+ },
ComposableDemo("Nested Scrolling") { NestedScrollingDemo() },
ComposableDemo("Nested Scaling") { NestedScalingDemo() },
- ComposableDemo("Drag and Scale") { DragAndScaleGestureDetectorDemo() },
+ ComposableDemo("Drag and Scale") { DragAndScaleGestureFilterDemo() },
ComposableDemo("Popup Drag") { PopupDragDemo() },
ComposableDemo("Double Tap in Tap") { DoubleTapInTapDemo() },
ComposableDemo("Nested Long Press") { NestedLongPressDemo() },
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt
index 271aaf3..6d47a3a 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/VectorGraphicsDemo.kt
@@ -33,7 +33,6 @@
import androidx.ui.graphics.vector.PathBuilder
import androidx.ui.graphics.vector.PathData
import androidx.ui.graphics.vector.VectorPainter
-import androidx.ui.graphics.vector.VectorScope
import androidx.ui.layout.Column
import androidx.ui.layout.preferredSize
import androidx.ui.layout.wrapContentSize
@@ -108,7 +107,7 @@
}
@Composable
-private fun VectorScope.BackgroundPath(vectorWidth: Float, vectorHeight: Float) {
+private fun BackgroundPath(vectorWidth: Float, vectorHeight: Float) {
val background = PathData {
horizontalLineTo(vectorWidth)
verticalLineTo(vectorHeight)
@@ -129,7 +128,7 @@
}
@Composable
-private fun VectorScope.Triangle() {
+private fun Triangle() {
val length = 150.0f
Path(
fill = RadialGradient(
@@ -152,7 +151,7 @@
}
@Composable
-private fun VectorScope.TriangleWithOffsets() {
+private fun TriangleWithOffsets() {
val side1 = 150.0f
val side2 = 150.0f
@@ -174,7 +173,7 @@
}
@Composable
-private fun VectorScope.StripePath(vectorWidth: Float, vectorHeight: Float) {
+private fun StripePath(vectorWidth: Float, vectorHeight: Float) {
val stripeDelegate = PathData {
stripe(vectorWidth, vectorHeight, 10)
}
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt
index 28573ff..edbb187 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/autofill/ExplicitAutofillTypesDemo.kt
@@ -25,9 +25,9 @@
import androidx.ui.core.AutofillTreeAmbient
import androidx.ui.core.LayoutCoordinates
import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
import androidx.ui.core.onChildPositioned
import androidx.ui.core.toComposeRect
+import androidx.ui.foundation.Box
import androidx.ui.foundation.Text
import androidx.ui.foundation.TextField
import androidx.ui.input.ImeAction
@@ -106,8 +106,7 @@
val autofillTree = AutofillTreeAmbient.current
autofillTree += autofillNode
- @Suppress("DEPRECATION")
- PassThroughLayout(onChildPositioned {
+ Box(Modifier.onChildPositioned {
autofillNode.boundingBox = it.boundingBox().toComposeRect()
}) {
children(autofillNode)
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt
index 8fcebd5..b2e2355 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/DragScaleGestureDetectorDemo.kt
@@ -37,11 +37,11 @@
import androidx.ui.unit.dp
/**
- * Simple demo that shows off how DragGestureDetector and ScaleGestureDetector automatically
+ * Simple demo that shows off how [dragGestureFilter] and [scaleGestureFilter] automatically
* interoperate.
*/
@Composable
-fun DragAndScaleGestureDetectorDemo() {
+fun DragAndScaleGestureFilterDemo() {
val size = state { 200.dp }
val offset = state { Offset.Zero }
val dragInScale = state { false }
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/HorizontalScrollersInVerticalScrollerDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/HorizontalScrollersInVerticalScrollerDemo.kt
new file mode 100644
index 0000000..9ad1b47
--- /dev/null
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/HorizontalScrollersInVerticalScrollerDemo.kt
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.demos.gestures
+
+import androidx.compose.Composable
+import androidx.compose.state
+import androidx.ui.core.Constraints
+import androidx.ui.core.ContentDrawScope
+import androidx.ui.core.Direction
+import androidx.ui.core.DrawModifier
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScrollCallback
+import androidx.ui.core.gesture.doubleTapGestureFilter
+import androidx.ui.core.gesture.longPressGestureFilter
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.tapGestureFilter
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.foundation.drawBackground
+import androidx.ui.foundation.drawBorder
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.drawscope.clipRect
+import androidx.ui.layout.Column
+import androidx.ui.layout.Row
+import androidx.ui.layout.preferredSize
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+import kotlin.math.roundToInt
+
+/**
+ * Demonstration for how multiple DragGestureDetectors interact.
+ */
+@Composable
+fun HorizontalScrollersInVerticalScrollersDemo() {
+ Column {
+ Text("Demonstrates scroll orientation locking.")
+ Text(
+ "There is a column of rows, all of which are scrollable. Any one pointer can only " +
+ "contribute to dragging in one orientation at a time."
+ )
+ Scrollable(Orientation.Vertical) {
+ RepeatingColumn(repetitions = 10) {
+ Box(paddingTop = 8.dp, paddingBottom = 8.dp) {
+ // Inner composable that scrolls
+ Scrollable(Orientation.Horizontal) {
+ RepeatingRow(repetitions = 10) {
+ // Composable that indicates it is being pressed
+ Pressable(
+ width = 96.dp,
+ height = 96.dp
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * A very simple ScrollView like implementation that allows for vertical scrolling.
+ */
+@Composable
+private fun Scrollable(orientation: Orientation, children: @Composable () -> Unit) {
+ val maxOffset = 0f
+ val offset = state { maxOffset }
+ val minOffset = state { 0f }
+
+ val scrollObserver = object : ScrollCallback {
+ override fun onScroll(scrollDistance: Float): Float {
+ val resultingOffset = offset.value + scrollDistance
+ val toConsume =
+ when {
+ resultingOffset > maxOffset -> {
+ maxOffset - offset.value
+ }
+ resultingOffset < minOffset.value -> {
+ minOffset.value - offset.value
+ }
+ else -> {
+ scrollDistance
+ }
+ }
+ offset.value = offset.value + toConsume
+ return toConsume
+ }
+ }
+
+ val canDrag: (Direction) -> Boolean = { direction ->
+ when {
+ direction == Direction.LEFT && offset.value > minOffset.value -> true
+ direction == Direction.UP && offset.value > minOffset.value -> true
+ direction == Direction.RIGHT && offset.value < maxOffset -> true
+ direction == Direction.DOWN && offset.value < maxOffset -> true
+ else -> false
+ }
+ }
+
+ Layout(
+ children = children,
+ modifier = Modifier.scrollGestureFilter(scrollObserver, orientation, canDrag) +
+ ClipModifier,
+ measureBlock = { measurables, constraints, _ ->
+ val placeable =
+ when (orientation) {
+ Orientation.Horizontal -> measurables.first().measure(
+ constraints.copy(
+ minWidth = 0,
+ maxWidth = Constraints.Infinity
+ )
+ )
+ Orientation.Vertical -> measurables.first().measure(
+ constraints.copy(
+ minHeight = 0,
+ maxHeight = Constraints.Infinity
+ )
+ )
+ }
+
+ minOffset.value =
+ when (orientation) {
+ Orientation.Horizontal -> constraints.maxWidth.toFloat() - placeable.width
+ Orientation.Vertical -> constraints.maxHeight.toFloat() - placeable.height
+ }
+
+ val width =
+ when (orientation) {
+ Orientation.Horizontal -> constraints.maxWidth
+ Orientation.Vertical -> placeable.width
+ }
+
+ val height =
+ when (orientation) {
+ Orientation.Horizontal -> placeable.height
+ Orientation.Vertical -> constraints.maxHeight
+ }
+
+ layout(width, height) {
+ when (orientation) {
+ Orientation.Horizontal -> placeable.place(offset.value.roundToInt(), 0)
+ Orientation.Vertical -> placeable.place(0, offset.value.roundToInt())
+ }
+ }
+ })
+}
+
+private val ClipModifier = object : DrawModifier {
+ override fun ContentDrawScope.draw() {
+ clipRect {
+ [email protected]()
+ }
+ }
+}
+
+/**
+ * A very simple Button like implementation that visually indicates when it is being pressed.
+ */
+@Composable
+private fun Pressable(
+ width: Dp,
+ height: Dp
+) {
+
+ val pressedColor = PressedColor
+ val defaultColor = Red
+
+ val color = state { defaultColor }
+ val showPressed = state { false }
+
+ val onPress: (Offset) -> Unit = {
+ showPressed.value = true
+ }
+
+ val onRelease = {
+ showPressed.value = false
+ }
+
+ val onTap: (Offset) -> Unit = {
+ color.value = color.value.next()
+ }
+
+ val onDoubleTap: (Offset) -> Unit = {
+ color.value = color.value.prev()
+ }
+
+ val onLongPress = { _: Offset ->
+ color.value = defaultColor
+ showPressed.value = false
+ }
+
+ val gestureDetectors =
+ Modifier
+ .pressIndicatorGestureFilter(onPress, onRelease, onRelease)
+ .tapGestureFilter(onTap)
+ .doubleTapGestureFilter(onDoubleTap)
+ .longPressGestureFilter(onLongPress)
+
+ val pressOverlay =
+ if (showPressed.value) Modifier.drawBackground(pressedColor) else Modifier
+
+ Box(
+ gestureDetectors
+ .preferredSize(width, height)
+ .drawBorder(1.dp, Color.Black)
+ .drawBackground(color.value)
+ .plus(pressOverlay)
+ )
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingColumn(repetitions: Int, children: @Composable () -> Unit) {
+ Column {
+ for (i in 1..repetitions) {
+ children()
+ }
+ }
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingRow(repetitions: Int, children: @Composable () -> Unit) {
+ Row {
+ for (i in 1..repetitions) {
+ children()
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt
index 5985ff0..9938ab2 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/NestedScrollingDemo.kt
@@ -24,11 +24,12 @@
import androidx.ui.core.Modifier
import androidx.ui.core.clipToBounds
import androidx.ui.core.gesture.doubleTapGestureFilter
-import androidx.ui.core.gesture.DragObserver
+import androidx.ui.core.gesture.ScrollCallback
import androidx.ui.core.gesture.longPressGestureFilter
import androidx.ui.core.gesture.pressIndicatorGestureFilter
import androidx.ui.core.gesture.tapGestureFilter
-import androidx.ui.core.gesture.dragGestureFilter
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
import androidx.ui.foundation.Border
import androidx.ui.foundation.Box
import androidx.ui.foundation.Text
@@ -52,12 +53,12 @@
Text("Demonstrates nested scrolling.")
Text("There are 3 fake vertical scrollers inside another vertical scroller. Try " +
"scrolling with 1 or many fingers.")
- Draggable {
- RepeatingList(repetitions = 3) {
+ Scrollable {
+ RepeatingColumn(repetitions = 3) {
Box(Modifier.preferredHeight(398.dp), padding = 72.dp) {
// Inner composable that scrolls
- Draggable {
- RepeatingList(repetitions = 5) {
+ Scrollable {
+ RepeatingColumn(repetitions = 5) {
// Composable that indicates it is being pressed
Pressable(
height = 72.dp
@@ -74,13 +75,13 @@
* A very simple ScrollView like implementation that allows for vertical scrolling.
*/
@Composable
-private fun Draggable(children: @Composable () -> Unit) {
+private fun Scrollable(children: @Composable () -> Unit) {
val offset = state { 0f }
val maxOffset = state { 0f }
- val dragObserver = object : DragObserver {
- override fun onDrag(dragDistance: Offset): Offset {
- val resultingOffset = offset.value + dragDistance.y
+ val scrollObserver = object : ScrollCallback {
+ override fun onScroll(scrollDistance: Float): Float {
+ val resultingOffset = offset.value + scrollDistance
val dyToConsume =
when {
resultingOffset > 0f -> {
@@ -90,11 +91,11 @@
maxOffset.value - offset.value
}
else -> {
- dragDistance.y
+ scrollDistance
}
}
- offset.value = offset.value + dyToConsume
- return Offset(0f, dyToConsume)
+ offset.value += dyToConsume
+ return dyToConsume
}
}
@@ -109,7 +110,7 @@
Layout(
children = children,
modifier = Modifier
- .dragGestureFilter(dragObserver, canDrag)
+ .scrollGestureFilter(scrollObserver, Orientation.Vertical, canDrag)
.clipToBounds(),
measureBlock = { measurables, constraints, _ ->
val placeable =
@@ -151,7 +152,7 @@
}
val onDoubleTap: (Offset) -> Unit = {
- color.value = color.value.prev().prev()
+ color.value = color.value.prev()
}
val onLongPress = { _: Offset ->
@@ -178,7 +179,7 @@
* times.
*/
@Composable
-private fun RepeatingList(repetitions: Int, row: @Composable () -> Unit) {
+private fun RepeatingColumn(repetitions: Int, row: @Composable () -> Unit) {
Column(Modifier.drawBorder(border = Border(2.dp, BorderColor))) {
for (i in 1..repetitions) {
row()
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/ScrollGestureFilterDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/ScrollGestureFilterDemo.kt
new file mode 100644
index 0000000..738cd5f
--- /dev/null
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/ScrollGestureFilterDemo.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.demos.gestures
+
+import androidx.compose.Composable
+import androidx.compose.emptyContent
+import androidx.compose.state
+import androidx.ui.core.Alignment
+import androidx.ui.core.DensityAmbient
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScrollCallback
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.layout.Column
+import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.offset
+import androidx.ui.layout.preferredSize
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+
+/**
+ * Simple demo that shows off ScrollGestureFilter.
+ */
+@Composable
+fun ScrollGestureFilterDemo() {
+ Column {
+ Text("Demonstrates scroll orientation locking")
+ Text(
+ "The inner box is composed inside of the outer. If you start dragging the inner box" +
+ "vertically, it will drag vertically , the same pointer will only ever allow " +
+ "the box to be dragged vertically. If drag the inner box horizontally, the " +
+ "container will start being dragged horizontally and that pointer will only " +
+ "ever drag horizontally."
+ )
+ ScrollableBox(240.dp, Orientation.Horizontal, Green, Yellow) {
+ ScrollableBox(144.dp, Orientation.Vertical, Red, Blue)
+ }
+ }
+}
+
+@Composable
+fun ScrollableBox(
+ size: Dp,
+ orientation: Orientation,
+ activeColor: Color,
+ idleColor: Color,
+ children: @Composable () -> Unit = emptyContent()
+) {
+
+ val color = state { idleColor }
+ val offsetPx = state { 0f }
+
+ val offsetDp = with(DensityAmbient.current) {
+ offsetPx.value.toDp()
+ }
+
+ val scrollCallback: ScrollCallback = object : ScrollCallback {
+ override fun onStart(downPosition: Offset) {
+ color.value = activeColor
+ }
+
+ override fun onScroll(scrollDistance: Float): Float {
+ offsetPx.value += scrollDistance
+ return scrollDistance
+ }
+
+ override fun onStop(velocity: Float) {
+ color.value = idleColor
+ }
+
+ override fun onCancel() {
+ color.value = idleColor
+ }
+ }
+
+ val (offsetX, offsetY) = when (orientation) {
+ Orientation.Horizontal -> offsetDp to Dp.Hairline
+ Orientation.Vertical -> Dp.Hairline to offsetDp
+ }
+
+ Box(
+ Modifier.offset(offsetX, offsetY)
+ .fillMaxSize()
+ .wrapContentSize(Alignment.Center)
+ .scrollGestureFilter(scrollCallback, orientation)
+ .preferredSize(size),
+ backgroundColor = color.value
+ ) {
+ children()
+ }
+}
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/VerticalScrollerInDrawerLayoutDemo.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/VerticalScrollerInDrawerLayoutDemo.kt
new file mode 100644
index 0000000..66eeb40
--- /dev/null
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/VerticalScrollerInDrawerLayoutDemo.kt
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.demos.gestures
+
+import androidx.compose.Composable
+import androidx.compose.state
+import androidx.ui.core.Alignment
+import androidx.ui.core.Constraints
+import androidx.ui.core.ContentDrawScope
+import androidx.ui.core.DensityAmbient
+import androidx.ui.core.Direction
+import androidx.ui.core.DrawModifier
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.core.gesture.ScrollCallback
+import androidx.ui.core.gesture.doubleTapGestureFilter
+import androidx.ui.core.gesture.longPressGestureFilter
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
+import androidx.ui.core.gesture.scrollGestureFilter
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.tapGestureFilter
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.foundation.drawBackground
+import androidx.ui.foundation.drawBorder
+import androidx.ui.geometry.Offset
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.drawscope.clipRect
+import androidx.ui.layout.Column
+import androidx.ui.layout.ColumnScope
+import androidx.ui.layout.Row
+import androidx.ui.layout.Stack
+import androidx.ui.layout.fillMaxHeight
+import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.fillMaxWidth
+import androidx.ui.layout.offsetPx
+import androidx.ui.layout.preferredHeight
+import androidx.ui.layout.width
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.unit.Dp
+import androidx.ui.unit.dp
+import kotlin.math.roundToInt
+
+/**
+ * Demonstration for how multiple DragGestureDetectors interact.
+ */
+@Composable
+fun VerticalScrollerInDrawerDemo() {
+ Column {
+ Text("Demonstrates scroll orientation locking.")
+ Text(
+ "There is a vertically scrolling column and a drawer layout. A pointer can only " +
+ "contribute to dragging the column or the drawer, but not both."
+ )
+ DrawerLayout(280.dp) {
+ Scrollable(Orientation.Vertical) {
+ RepeatingColumn(repetitions = 10) {
+ Pressable(
+ height = 96.dp
+ )
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun DrawerLayout(drawerWidth: Dp, children: @Composable ColumnScope.() -> Unit) {
+
+ val minOffset =
+ with(DensityAmbient.current) {
+ -drawerWidth.toPx()
+ }
+
+ val currentOffset = state { minOffset }
+ val maxOffset = 0f
+
+ val scrollObserver = object : ScrollCallback {
+ override fun onScroll(scrollDistance: Float): Float {
+ val originalOffset = currentOffset.value
+ currentOffset.value =
+ (currentOffset.value + scrollDistance).coerceIn(minOffset, maxOffset)
+ return currentOffset.value - originalOffset
+ }
+ }
+
+ val canDrag: (Direction) -> Boolean =
+ { direction ->
+ when (direction) {
+ Direction.LEFT -> currentOffset.value > minOffset
+ Direction.RIGHT -> currentOffset.value < 0
+ else -> false
+ }
+ }
+
+ Stack(Modifier.scrollGestureFilter(scrollObserver, Orientation.Horizontal, canDrag)) {
+ Column {
+ children()
+ }
+ Box(
+ Modifier
+ .fillMaxHeight()
+ .width(drawerWidth)
+ .offsetPx(x = currentOffset)
+ .drawBackground(DefaultBackgroundColor)
+ ) {
+ Text(
+ "This is empty drawer content",
+ Modifier
+ .fillMaxSize()
+ .wrapContentSize(Alignment.Center)
+ )
+ }
+ }
+}
+
+/**
+ * A very simple ScrollView like implementation that allows for vertical scrolling.
+ */
+@Composable
+private fun Scrollable(orientation: Orientation, children: @Composable () -> Unit) {
+ val maxOffset = 0f
+ val offset = state { maxOffset }
+ val minOffset = state { 0f }
+
+ val scrollObserver = object : ScrollCallback {
+ override fun onScroll(scrollDistance: Float): Float {
+ val resultingOffset = offset.value + scrollDistance
+ val toConsume =
+ when {
+ resultingOffset > maxOffset -> {
+ maxOffset - offset.value
+ }
+ resultingOffset < minOffset.value -> {
+ minOffset.value - offset.value
+ }
+ else -> {
+ scrollDistance
+ }
+ }
+ offset.value = offset.value + toConsume
+ return toConsume
+ }
+ }
+
+ val canDrag: (Direction) -> Boolean = { direction ->
+ when {
+ direction == Direction.LEFT && offset.value > minOffset.value -> true
+ direction == Direction.UP && offset.value > minOffset.value -> true
+ direction == Direction.RIGHT && offset.value < maxOffset -> true
+ direction == Direction.DOWN && offset.value < maxOffset -> true
+ else -> false
+ }
+ }
+
+ Layout(
+ children = children,
+ modifier = Modifier.scrollGestureFilter(scrollObserver, orientation, canDrag) +
+ ClipModifier,
+ measureBlock = { measurables, constraints, _ ->
+ val placeable =
+ when (orientation) {
+ Orientation.Horizontal -> measurables.first().measure(
+ constraints.copy(
+ minWidth = 0,
+ maxWidth = Constraints.Infinity
+ )
+ )
+ Orientation.Vertical -> measurables.first().measure(
+ constraints.copy(
+ minHeight = 0,
+ maxHeight = Constraints.Infinity
+ )
+ )
+ }
+
+ minOffset.value =
+ when (orientation) {
+ Orientation.Horizontal -> constraints.maxWidth.toFloat() - placeable.width
+ Orientation.Vertical -> constraints.maxHeight.toFloat() - placeable.height
+ }
+
+ val width =
+ when (orientation) {
+ Orientation.Horizontal -> constraints.maxWidth
+ Orientation.Vertical -> placeable.width
+ }
+
+ val height =
+ when (orientation) {
+ Orientation.Horizontal -> placeable.height
+ Orientation.Vertical -> constraints.maxHeight
+ }
+
+ layout(width, height) {
+ when (orientation) {
+ Orientation.Horizontal -> placeable.place(offset.value.roundToInt(), 0)
+ Orientation.Vertical -> placeable.place(0, offset.value.roundToInt())
+ }
+ }
+ })
+}
+
+private val ClipModifier = object : DrawModifier {
+ override fun ContentDrawScope.draw() {
+ clipRect {
+ [email protected]()
+ }
+ }
+}
+
+/**
+ * A very simple Button like implementation that visually indicates when it is being pressed.
+ */
+@Composable
+private fun Pressable(
+ height: Dp
+) {
+
+ val pressedColor = PressedColor
+ val defaultColor = Red
+
+ val color = state { defaultColor }
+ val showPressed = state { false }
+
+ val onPress: (Offset) -> Unit = {
+ showPressed.value = true
+ }
+
+ val onRelease = {
+ showPressed.value = false
+ }
+
+ val onTap: (Offset) -> Unit = {
+ color.value = color.value.next()
+ }
+
+ val onDoubleTap: (Offset) -> Unit = {
+ color.value = color.value.prev()
+ }
+
+ val onLongPress = { _: Offset ->
+ color.value = defaultColor
+ showPressed.value = false
+ }
+
+ val gestureDetectors =
+ Modifier
+ .pressIndicatorGestureFilter(onPress, onRelease, onRelease)
+ .tapGestureFilter(onTap)
+ .doubleTapGestureFilter(onDoubleTap)
+ .longPressGestureFilter(onLongPress)
+
+ val pressOverlay =
+ if (showPressed.value) Modifier.drawBackground(pressedColor) else Modifier
+
+ Box(
+ Modifier
+ .fillMaxWidth()
+ .preferredHeight(height)
+ .drawBorder(1.dp, Color.Black)
+ .drawBackground(color.value)
+ .plus(pressOverlay) + gestureDetectors
+ )
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingColumn(repetitions: Int, children: @Composable () -> Unit) {
+ Column {
+ for (i in 1..repetitions) {
+ children()
+ }
+ }
+}
+
+/**
+ * A simple composable that repeats its children as a vertical list of divided items [repetitions]
+ * times.
+ */
+@Suppress("SameParameterValue")
+@Composable
+private fun RepeatingRow(repetitions: Int, children: @Composable () -> Unit) {
+ Row {
+ for (i in 1..repetitions) {
+ children()
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt
index 2387c2c..562e520 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/viewinterop/ViewInCompose.kt
@@ -38,6 +38,7 @@
import androidx.ui.layout.Column
import androidx.ui.material.Button
import androidx.ui.viewinterop.AndroidView
+import androidx.ui.viewinterop.emitView
@Composable
fun ViewInComposeDemo() {
@@ -46,10 +47,14 @@
// UI hierarchies. Note that these APIs are subject to change.
// Include Android View.
- TextView(text = "This is a text in a TextView")
+ emitView(::TextView) {
+ it.text = "This is a text in a TextView"
+ }
val ref = Ref<View>()
- FrameLayout(ref = ref) {
- android.widget.TextView(text = "This is a very long very long text")
+ emitView(::FrameLayout, { it.setRef(ref) }) {
+ emitView(::TextView) {
+ it.text = "This is a very long very long text"
+ }
}
Text("This is a second text")
ref.value!!.layoutParams = ViewGroup.LayoutParams(100, WRAP_CONTENT)
@@ -67,12 +72,12 @@
// Compose custom Android View and do remeasurements and invalidates.
val squareRef = Ref<ColoredSquareView>()
- FrameLayout {
- ColoredSquareView(
- size = 200,
- color = Color.Cyan,
- ref = squareRef
- )
+ emitView(::FrameLayout, {}) {
+ emitView(::ColoredSquareView) {
+ it.size = 200
+ it.color = Color.Cyan
+ it.setRef(squareRef)
+ }
}
Button(onClick = { squareRef.value!!.size += 50 }) {
Text("Increase size of Android view")
diff --git a/ui/ui-core/samples/src/main/java/androidx/ui/core/samples/EmitViewSamples.kt b/ui/ui-core/samples/src/main/java/androidx/ui/core/samples/EmitViewSamples.kt
new file mode 100644
index 0000000..0c3cb3b
--- /dev/null
+++ b/ui/ui-core/samples/src/main/java/androidx/ui/core/samples/EmitViewSamples.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.samples
+
+import android.view.View
+import androidx.annotation.Sampled
+import androidx.compose.Composable
+import android.widget.Button
+import android.widget.LinearLayout
+import androidx.ui.viewinterop.emitView
+
+@Sampled
+@Composable
+fun EmitViewButtonSample() {
+ @Composable
+ fun Button(
+ text: String,
+ onClick: (() -> Unit)? = null
+ ) {
+ emitView<Button>(::Button) {
+ it.text = text
+ it.setOnClickListener(onClick?.let { View.OnClickListener { it() } })
+ }
+ }
+}
+
+@Sampled
+@Composable
+fun EmitViewLinearLayoutSample() {
+ @Composable
+ fun LinearLayout(
+ orientation: Int = android.widget.LinearLayout.VERTICAL,
+ children: @Composable () -> Unit
+ ) {
+ emitView<LinearLayout>(::LinearLayout, { it.orientation = orientation }) {
+ children()
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt
index a86da8a..ed0d0f6 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/AndroidPointerInputTest.kt
@@ -25,7 +25,6 @@
import androidx.compose.FrameManager
import androidx.compose.Recomposer
import androidx.compose.emptyContent
-import androidx.compose.escapeCompose
import androidx.compose.getValue
import androidx.compose.mutableStateOf
import androidx.compose.remember
@@ -348,13 +347,12 @@
@Composable
fun AndroidWithCompose(context: Context, androidPadding: Int, children: @Composable () -> Unit) {
- val anotherLayout =
- escapeCompose { FrameLayout(context) }.also { view ->
- view.setContent(Recomposer.current()) {
- children()
- }
- view.setPadding(androidPadding, androidPadding, androidPadding, androidPadding)
+ val anotherLayout = FrameLayout(context).also { view ->
+ view.setContent(Recomposer.current()) {
+ children()
}
+ view.setPadding(androidPadding, androidPadding, androidPadding, androidPadding)
+ }
AndroidView(anotherLayout)
}
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt
index 58b1eb9..b2ebce3 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/HotReloadTests.kt
@@ -22,12 +22,14 @@
import android.widget.TextView
import androidx.compose.clearRoots
import androidx.compose.Composable
+import androidx.compose.emit
import androidx.compose.onCommit
import androidx.compose.simulateHotReload
import androidx.test.filters.MediumTest
import androidx.ui.core.semantics.semantics
import androidx.ui.foundation.Box
import androidx.ui.framework.test.TestActivity
+import androidx.ui.node.UiApplier
import androidx.ui.semantics.accessibilityLabel
import androidx.ui.test.android.AndroidComposeTestRule
import androidx.ui.test.assertLabelEquals
@@ -62,11 +64,23 @@
var value = "First value"
@Composable fun text(text: String, id: Int = -1) {
- TextView(id = id, text = text)
+ val context = ContextAmbient.current
+ emit<TextView, UiApplier>(
+ ctor = { TextView(context) },
+ update = {
+ set(id) { this.id = it }
+ set(text) { this.text = it }
+ }
+ )
}
@Composable fun column(children: @Composable () -> Unit) {
- LinearLayout { children() }
+ val context = ContextAmbient.current
+ emit<LinearLayout, UiApplier>(
+ ctor = { LinearLayout(context) },
+ update = {},
+ children = children
+ )
}
val composeLatch = CountDownLatch(1)
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt
index b9852fa..97c6aba 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/selection/SelectionHandlesTest.kt
@@ -26,6 +26,7 @@
import androidx.ui.framework.test.TestActivity
import androidx.ui.graphics.Color
import androidx.ui.graphics.toArgb
+import androidx.ui.text.InternalTextApi
import androidx.ui.text.style.TextDirection
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.mock
@@ -38,6 +39,7 @@
@SmallTest
@RunWith(JUnit4::class)
+@OptIn(InternalTextApi::class)
class SelectionHandlesTest {
@Suppress("DEPRECATION")
@get:Rule
@@ -87,9 +89,15 @@
fun StartSelectionHandle_left_pointing() {
rule.runOnUiThreadIR {
activity.setContent {
- SelectionHandle(Modifier,
+ SelectionHandle(
+ modifier = Modifier,
isStartHandle = true,
- selection = selectionLtrHandleDirection)
+ directions = Pair(
+ selectionLtrHandleDirection.start.direction,
+ selectionLtrHandleDirection.end.direction
+ ),
+ handlesCrossed = selectionLtrHandleDirection.handlesCrossed
+ )
}
}
@@ -105,9 +113,15 @@
fun StartSelectionHandle_right_pointing() {
rule.runOnUiThreadIR {
activity.setContent {
- SelectionHandle(Modifier,
+ SelectionHandle(
+ modifier = Modifier,
isStartHandle = true,
- selection = selectionRtlHandleDirection)
+ directions = Pair(
+ selectionRtlHandleDirection.start.direction,
+ selectionRtlHandleDirection.end.direction
+ ),
+ handlesCrossed = selectionRtlHandleDirection.handlesCrossed
+ )
}
}
@@ -123,9 +137,15 @@
fun EndSelectionHandle_right_pointing() {
rule.runOnUiThreadIR {
activity.setContent {
- SelectionHandle(Modifier,
+ SelectionHandle(
+ modifier = Modifier,
isStartHandle = false,
- selection = selectionLtrHandleDirection)
+ directions = Pair(
+ selectionLtrHandleDirection.start.direction,
+ selectionLtrHandleDirection.end.direction
+ ),
+ handlesCrossed = selectionLtrHandleDirection.handlesCrossed
+ )
}
}
@@ -141,9 +161,15 @@
fun EndSelectionHandle_left_pointing() {
rule.runOnUiThreadIR {
activity.setContent {
- SelectionHandle(Modifier,
+ SelectionHandle(
+ modifier = Modifier,
isStartHandle = false,
- selection = selectionRtlHandleDirection)
+ directions = Pair(
+ selectionRtlHandleDirection.start.direction,
+ selectionRtlHandleDirection.end.direction
+ ),
+ handlesCrossed = selectionRtlHandleDirection.handlesCrossed
+ )
}
}
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt
index f66e670..8d7708a 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidLayoutDrawTest.kt
@@ -56,7 +56,6 @@
import androidx.ui.core.Modifier
import androidx.ui.core.Owner
import androidx.ui.core.ParentDataModifier
-import androidx.ui.core.PassThroughLayout
import androidx.ui.core.Ref
import androidx.ui.core.VerticalAlignmentLine
import androidx.ui.core.constrainHeight
@@ -87,6 +86,7 @@
import androidx.ui.unit.dp
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
@@ -2325,27 +2325,6 @@
assertFalse(outerLatch.await(200, TimeUnit.MILLISECONDS))
}
- @Test
- fun passThroughLayout_passesThroughParentData() {
- val latch = CountDownLatch(1)
- activityTestRule.runOnUiThread {
- activity.setContent {
- Layout({
- PassThroughLayout {
- FixedSize(50, Modifier.layoutId("1"))
- }
- }) { measurables, constraints, _ ->
- assertEquals("1", measurables[0].id)
- val placeable = measurables[0].measure(constraints)
- assertEquals(50, placeable.width)
- latch.countDown()
- layout(0, 0) {}
- }
- }
- }
- assertTrue(latch.await(1, TimeUnit.SECONDS))
- }
-
// When a child with a layer is removed with its children, it shouldn't crash.
@Test
fun detachChildWithLayer() {
@@ -2461,6 +2440,106 @@
}
}
+ // Delegates don't change when the modifier types remain the same
+ @Test
+ fun instancesKeepDelegates() {
+ var color by mutableStateOf(Color.Red)
+ var m: Measurable? = null
+ val layoutCaptureModifier = object : LayoutModifier {
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints,
+ layoutDirection: LayoutDirection
+ ): MeasureScope.MeasureResult {
+ m = measurable
+ val p = measurable.measure(constraints, layoutDirection)
+ drawLatch.countDown()
+ return layout(p.width, p.height) {
+ p.place(0, 0)
+ }
+ }
+ }
+ activityTestRule.runOnUiThread {
+ activity.setContent {
+ FixedSize(30, layoutCaptureModifier.background(color)) {}
+ }
+ }
+ assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+ var firstMeasurable = m
+ drawLatch = CountDownLatch(1)
+
+ activityTestRule.runOnUiThread {
+ m = null
+ color = Color.Blue
+ }
+
+ assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+ assertNotNull(m)
+ assertSame(firstMeasurable, m)
+ }
+
+ // LayoutNodeWrappers remain even when there are multiple for a modifier
+ @Test
+ fun replaceMultiImplementationModifier() {
+ var color by mutableStateOf(Color.Red)
+ var m: Measurable? = null
+
+ var layerLatch = CountDownLatch(1)
+
+ class SpecialModifier(
+ val drawLatch: CountDownLatch,
+ val layerLatch: CountDownLatch
+ ) : DrawModifier, DrawLayerModifier {
+ override fun ContentDrawScope.draw() {
+ drawContent()
+ drawLatch.countDown()
+ }
+
+ override val translationX: Float
+ get() {
+ layerLatch.countDown()
+ return super.translationX
+ }
+ }
+
+ val layoutCaptureModifier = object : LayoutModifier {
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints,
+ layoutDirection: LayoutDirection
+ ): MeasureScope.MeasureResult {
+ m = measurable
+ val p = measurable.measure(constraints, layoutDirection)
+ return layout(p.width, p.height) {
+ p.place(0, 0)
+ }
+ }
+ }
+ activityTestRule.runOnUiThread {
+ activity.setContent {
+ FixedSize(30, layoutCaptureModifier +
+ SpecialModifier(drawLatch, layerLatch).background(color)) {}
+ }
+ }
+ assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+ assertTrue(layerLatch.await(1, TimeUnit.SECONDS))
+ var firstMeasurable = m
+ drawLatch = CountDownLatch(1)
+ layerLatch = CountDownLatch(1)
+
+ activityTestRule.runOnUiThread {
+ m = null
+ color = Color.Blue
+ }
+
+ // The latches are triggered in the new instance
+ assertTrue(drawLatch.await(1, TimeUnit.SECONDS))
+ assertTrue(layerLatch.await(1, TimeUnit.SECONDS))
+ // The new instance's measurable is the same.
+ assertNotNull(m)
+ assertSame(firstMeasurable, m)
+ }
+
private fun composeSquares(model: SquareModel) {
activityTestRule.runOnUiThreadIR {
activity.setContent {
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt
index 8f37987..2862ab1 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/core/test/AndroidViewCompatTest.kt
@@ -56,6 +56,7 @@
import androidx.ui.test.runOnIdleCompose
import androidx.ui.test.runOnUiThread
import androidx.ui.unit.IntOffset
+import androidx.ui.viewinterop.emitView
import junit.framework.TestCase.assertNotNull
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.instanceOf
@@ -84,7 +85,11 @@
Layout(
modifier = Modifier.testTag("content"),
children = @Composable {
- ColoredSquareView(size = squareSize.value, ref = squareRef)
+
+ emitView(::ColoredSquareView) {
+ it.size = squareSize.value
+ it.ref = squareRef
+ }
}
) { measurables, constraints, _ ->
assertEquals(1, measurables.size)
@@ -140,7 +145,10 @@
composeTestRule.setContent {
Align {
Container(Modifier.testTag("content").drawLayer()) {
- ColoredSquareView(color = colorModel.value, ref = squareRef)
+ emitView(::ColoredSquareView) {
+ it.color = colorModel.value
+ it.ref = squareRef
+ }
}
}
}
@@ -328,11 +336,11 @@
composeTestRule.setContent {
Container(LayoutConstraints(constraintsHolder.value)) {
- MeasureSpecSaverView(
- ref = viewRef,
- widthMeasureSpecRef = widthMeasureSpecRef,
- heightMeasureSpecRef = heightMeasureSpecRef
- )
+ emitView(::MeasureSpecSaverView) {
+ it.ref = viewRef
+ it.widthMeasureSpecRef = widthMeasureSpecRef
+ it.heightMeasureSpecRef = heightMeasureSpecRef
+ }
}
}
@@ -353,7 +361,7 @@
val constraintsHolder = mutableStateOf(Constraints())
composeTestRule.setContent {
Container(LayoutConstraints(constraintsHolder.value)) {
- MeasureSpecSaverView(ref = viewRef)
+ emitView(::MeasureSpecSaverView) { it.ref = viewRef }
}
}
runOnUiThread {
@@ -445,4 +453,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt
index 2324088..658288a 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/compat/XmlVectorParserTest.kt
@@ -63,16 +63,16 @@
assertEquals(10.0f, moveTo.y)
val relativeLineTo1 = path[1].assertType<PathNode.RelativeLineTo>()
- assertEquals(10.0f, relativeLineTo1.x)
- assertEquals(0.0f, relativeLineTo1.y)
+ assertEquals(10.0f, relativeLineTo1.dx)
+ assertEquals(0.0f, relativeLineTo1.dy)
val relativeLineTo2 = path[2].assertType<PathNode.RelativeLineTo>()
- assertEquals(0.0f, relativeLineTo2.x)
- assertEquals(10.0f, relativeLineTo2.y)
+ assertEquals(0.0f, relativeLineTo2.dx)
+ assertEquals(10.0f, relativeLineTo2.dy)
val relativeLineTo3 = path[3].assertType<PathNode.RelativeLineTo>()
- assertEquals(-10.0f, relativeLineTo3.x)
- assertEquals(0.0f, relativeLineTo3.y)
+ assertEquals(-10.0f, relativeLineTo3.dx)
+ assertEquals(0.0f, relativeLineTo3.dy)
path[4].assertType<PathNode.Close>()
}
diff --git a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt
index 288ace5..427e094 100644
--- a/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt
+++ b/ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/viewinterop/ComposedViewTest.kt
@@ -16,6 +16,7 @@
package androidx.ui.viewinterop
+import android.os.Build
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.ViewGroup
@@ -30,6 +31,7 @@
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withClassName
+import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import androidx.ui.core.Modifier
import androidx.ui.core.test.R
@@ -171,6 +173,7 @@
}
@Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun androidViewWithView_drawModifierIsApplied() {
val size = 300
lateinit var frameLayout: FrameLayout
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/compose/ComposerCompat.kt b/ui/ui-core/src/androidMain/kotlin/androidx/compose/ComposerCompat.kt
deleted file mode 100644
index 93ff04a..0000000
--- a/ui/ui-core/src/androidMain/kotlin/androidx/compose/ComposerCompat.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose
-
-import androidx.ui.node.UiComposer
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
- "This property should not be called directly. It is only used by the compiler.",
- replaceWith = ReplaceWith("currentComposer")
-)
-val composer: UiComposer
- get() = error(
- "This property should not be called directly. It is only used by the compiler."
- )
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
index adbcceb..f6bb774 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
@@ -31,14 +31,11 @@
import android.view.View
import android.view.ViewGroup
import android.view.ViewStructure
-import android.view.accessibility.AccessibilityEvent
-import android.view.accessibility.AccessibilityManager
import android.view.autofill.AutofillValue
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import androidx.core.os.HandlerCompat
import androidx.core.view.ViewCompat
-import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.ViewTreeLifecycleOwner
@@ -63,8 +60,6 @@
import androidx.ui.core.semantics.SemanticsNode
import androidx.ui.core.semantics.SemanticsModifierCore
import androidx.ui.core.semantics.SemanticsOwner
-import androidx.ui.core.semantics.getAllSemanticsNodesToMap
-import androidx.ui.core.semantics.getOrNull
import androidx.ui.core.text.AndroidFontResourceLoader
import androidx.ui.core.texttoolbar.AndroidTextToolbar
import androidx.ui.core.texttoolbar.TextToolbar
@@ -80,11 +75,9 @@
import androidx.ui.input.TextInputServiceAndroid
import androidx.ui.input.textInputServiceFactory
import androidx.ui.savedinstancestate.UiSavedStateRegistry
-import androidx.ui.semantics.SemanticsProperties
import androidx.ui.text.font.Font
import androidx.ui.unit.Density
import androidx.ui.unit.IntOffset
-import androidx.ui.unit.max
import androidx.ui.util.fastForEach
import androidx.ui.util.trace
import java.lang.reflect.Method
@@ -116,14 +109,12 @@
) : ViewGroup(context), AndroidOwner {
override val view: View = this
- private val accessibilityDelegate = AndroidComposeViewAccessibilityDelegateCompat(this)
override var density = Density(context)
private set
private val semanticsModifier = SemanticsModifierCore(
id = SemanticsNode.generateNewId(),
- applyToChildLayoutNode = false,
mergeAllDescendants = false,
properties = null
)
@@ -137,23 +128,8 @@
it.modifier = Modifier.drawLayer() + semanticsModifier + focusModifier + keyInputModifier
}
- private inner class SemanticsNodeCopy(
- semanticsNode: SemanticsNode
- ) {
- val config = semanticsNode.config
- val children: MutableSet<Int> = mutableSetOf()
-
- init {
- semanticsNode.children.fastForEach { child ->
- children.add(child.id)
- }
- }
- }
-
override val semanticsOwner: SemanticsOwner = SemanticsOwner(root)
- private var semanticsNodes: MutableMap<Int, SemanticsNodeCopy> = mutableMapOf()
- private var semanticsRoot = SemanticsNodeCopy(semanticsOwner.rootSemanticsNode)
- private var checkingForSemanticsChanges = false
+ private val accessibilityDelegate = AndroidComposeViewAccessibilityDelegateCompat(this)
// Used by components that want to provide autofill semantic information.
// TODO: Replace with SemanticsTree: Temporary hack until we have a semantics tree implemented.
@@ -199,16 +175,6 @@
}
}
- override fun dispatchWindowFocusChanged(hasFocus: Boolean) {
- Log.d(FOCUS_TAG, "Owner WindowFocusChanged($hasFocus)")
- // If the focus state is not Inactive, it indicates that this is not the first time that
- // this Window got focus. So we maintain the previous focus state.
- if (hasFocus && focusModifier.focusDetailedState == Inactive) {
- focusModifier.focusDetailedState = Active
- // TODO(b/152535715): propagate focus to children based on child focusability.
- }
- }
-
override fun sendKeyEvent(keyEvent: KeyEvent): Boolean {
return keyInputModifier.processKeyInput(keyEvent)
}
@@ -312,15 +278,20 @@
private val measureAndLayoutDelegate = MeasureAndLayoutDelegate(root)
+ private var measureAndLayoutScheduled = false
+
private val measureAndLayoutHandler: Handler =
HandlerCompat.createAsync(Looper.getMainLooper()) {
+ measureAndLayoutScheduled = false
measureAndLayout()
true
}
private fun scheduleMeasureAndLayout() {
- measureAndLayoutHandler.removeMessages(0)
- measureAndLayoutHandler.sendEmptyMessage(0)
+ if (!isLayoutRequested && !measureAndLayoutScheduled) {
+ measureAndLayoutScheduled = true
+ measureAndLayoutHandler.sendEmptyMessage(0)
+ }
}
override val measureIteration: Long get() = measureAndLayoutDelegate.measureIteration
@@ -415,15 +386,7 @@
}
override fun onSemanticsChange() {
- if ((context.getSystemService(Context.ACCESSIBILITY_SERVICE)
- as AccessibilityManager).isEnabled && !checkingForSemanticsChanges
- ) {
- checkingForSemanticsChanges = true
- Handler(Looper.getMainLooper()).post {
- checkForSemanticsChanges()
- checkingForSemanticsChanges = false
- }
- }
+ accessibilityDelegate.onSemanticsChange()
}
private fun updateLayerProperties(layer: OwnedLayer) {
@@ -432,94 +395,6 @@
}
}
- private fun checkForSemanticsChanges() {
- val newSemanticsNodes = semanticsOwner.getAllSemanticsNodesToMap()
-
- // Structural change
- sendSemanticsStructureChangeEvents(semanticsOwner.rootSemanticsNode, semanticsRoot)
-
- // Property change
- for (id in newSemanticsNodes.keys) {
- if (semanticsNodes.contains(id)) {
- // We do doing this search because the new configuration is set as a whole, so we
- // can't indicate which property is changed when setting the new configuration.
- var newNode = newSemanticsNodes[id]
- var oldNode = semanticsNodes[id]
- for (entry in newNode!!.config) {
- if (entry.value == oldNode!!.config.getOrNull(entry.key)) {
- continue
- }
- when (entry.key) {
- // we are in aosp, so can't use the state description yet.
- SemanticsProperties.AccessibilityValue,
- SemanticsProperties.AccessibilityLabel ->
- accessibilityDelegate.sendEventForVirtualView(
- semanticsNodeIdToAccessibilityVirtualNodeId(id),
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
- AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
- entry.value as CharSequence
- )
- else -> {
- // TODO(b/151840490) send the correct events when property changes
- }
- }
- }
- }
- }
-
- // Update the cache
- semanticsNodes.clear()
- for (entry in newSemanticsNodes.entries) {
- semanticsNodes[entry.key] = SemanticsNodeCopy(entry.value)
- }
- semanticsRoot = SemanticsNodeCopy(semanticsOwner.rootSemanticsNode)
- }
-
- private fun sendSemanticsStructureChangeEvents(
- newNode: SemanticsNode,
- oldNode: SemanticsNodeCopy
- ) {
- var newChildren: MutableSet<Int> = mutableSetOf()
-
- // If any child is added, clear the subtree rooted at this node and return.
- newNode.children.fastForEach { child ->
- if (!oldNode.children.contains(child.id)) {
- accessibilityDelegate.sendEventForVirtualView(
- semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
- AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
- null
- )
- return
- }
- newChildren.add(child.id)
- }
-
- // If any child is deleted, clear the subtree rooted at this node and return.
- for (child in oldNode.children) {
- if (!newChildren.contains(child)) {
- accessibilityDelegate.sendEventForVirtualView(
- semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
- AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
- null
- )
- return
- }
- }
-
- newNode.children.fastForEach { child ->
- sendSemanticsStructureChangeEvents(child, semanticsNodes[child.id]!!)
- }
- }
-
- private fun semanticsNodeIdToAccessibilityVirtualNodeId(id: Int): Int {
- if (id == semanticsOwner.rootSemanticsNode.id) {
- return AccessibilityNodeProviderCompat.HOST_VIEW_ID
- }
- return id
- }
-
override fun dispatchDraw(canvas: android.graphics.Canvas) {
measureAndLayout()
// we don't have to observe here because the root has a layer modifier
@@ -586,6 +461,9 @@
super.onDetachedFromWindow()
modelObserver.enableModelUpdatesObserving(false)
ifDebug { if (autofillSupported()) _autofill?.unregisterCallback() }
+ if (measureAndLayoutScheduled) {
+ measureAndLayoutHandler.removeMessages(0)
+ }
root.detach()
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
index a43eb7b..66052a2 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
@@ -18,6 +18,8 @@
import android.content.Context
import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
@@ -33,6 +35,7 @@
import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
import androidx.ui.core.semantics.SemanticsNode
import androidx.ui.core.semantics.findChildById
+import androidx.ui.core.semantics.getAllSemanticsNodesToMap
import androidx.ui.core.semantics.getOrNull
import androidx.ui.semantics.CustomAccessibilityAction
import androidx.ui.semantics.SemanticsActions
@@ -52,45 +55,45 @@
*/
const val ParcelSafeTextLength = 100000
private val AccessibilityActionsResourceIds = intArrayOf(
- androidx.ui.core.R.id.accessibility_custom_action_0,
- androidx.ui.core.R.id.accessibility_custom_action_1,
- androidx.ui.core.R.id.accessibility_custom_action_2,
- androidx.ui.core.R.id.accessibility_custom_action_3,
- androidx.ui.core.R.id.accessibility_custom_action_4,
- androidx.ui.core.R.id.accessibility_custom_action_5,
- androidx.ui.core.R.id.accessibility_custom_action_6,
- androidx.ui.core.R.id.accessibility_custom_action_7,
- androidx.ui.core.R.id.accessibility_custom_action_8,
- androidx.ui.core.R.id.accessibility_custom_action_9,
- androidx.ui.core.R.id.accessibility_custom_action_10,
- androidx.ui.core.R.id.accessibility_custom_action_11,
- androidx.ui.core.R.id.accessibility_custom_action_12,
- androidx.ui.core.R.id.accessibility_custom_action_13,
- androidx.ui.core.R.id.accessibility_custom_action_14,
- androidx.ui.core.R.id.accessibility_custom_action_15,
- androidx.ui.core.R.id.accessibility_custom_action_16,
- androidx.ui.core.R.id.accessibility_custom_action_17,
- androidx.ui.core.R.id.accessibility_custom_action_18,
- androidx.ui.core.R.id.accessibility_custom_action_19,
- androidx.ui.core.R.id.accessibility_custom_action_20,
- androidx.ui.core.R.id.accessibility_custom_action_21,
- androidx.ui.core.R.id.accessibility_custom_action_22,
- androidx.ui.core.R.id.accessibility_custom_action_23,
- androidx.ui.core.R.id.accessibility_custom_action_24,
- androidx.ui.core.R.id.accessibility_custom_action_25,
- androidx.ui.core.R.id.accessibility_custom_action_26,
- androidx.ui.core.R.id.accessibility_custom_action_27,
- androidx.ui.core.R.id.accessibility_custom_action_28,
- androidx.ui.core.R.id.accessibility_custom_action_29,
- androidx.ui.core.R.id.accessibility_custom_action_30,
- androidx.ui.core.R.id.accessibility_custom_action_31
+ R.id.accessibility_custom_action_0,
+ R.id.accessibility_custom_action_1,
+ R.id.accessibility_custom_action_2,
+ R.id.accessibility_custom_action_3,
+ R.id.accessibility_custom_action_4,
+ R.id.accessibility_custom_action_5,
+ R.id.accessibility_custom_action_6,
+ R.id.accessibility_custom_action_7,
+ R.id.accessibility_custom_action_8,
+ R.id.accessibility_custom_action_9,
+ R.id.accessibility_custom_action_10,
+ R.id.accessibility_custom_action_11,
+ R.id.accessibility_custom_action_12,
+ R.id.accessibility_custom_action_13,
+ R.id.accessibility_custom_action_14,
+ R.id.accessibility_custom_action_15,
+ R.id.accessibility_custom_action_16,
+ R.id.accessibility_custom_action_17,
+ R.id.accessibility_custom_action_18,
+ R.id.accessibility_custom_action_19,
+ R.id.accessibility_custom_action_20,
+ R.id.accessibility_custom_action_21,
+ R.id.accessibility_custom_action_22,
+ R.id.accessibility_custom_action_23,
+ R.id.accessibility_custom_action_24,
+ R.id.accessibility_custom_action_25,
+ R.id.accessibility_custom_action_26,
+ R.id.accessibility_custom_action_27,
+ R.id.accessibility_custom_action_28,
+ R.id.accessibility_custom_action_29,
+ R.id.accessibility_custom_action_30,
+ R.id.accessibility_custom_action_31
)
}
/** Virtual view id for the currently hovered logical item. */
private var hoveredVirtualViewId = InvalidId
private val accessibilityManager: AccessibilityManager =
- view.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE) as
- AccessibilityManager
+ view.context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
+ private val handler = Handler(Looper.getMainLooper())
private var nodeProvider: AccessibilityNodeProviderCompat = MyNodeProvider()
private var focusedVirtualViewId = InvalidId
// For actionIdToId and labelToActionId, the keys are the virtualViewIds. The value of
@@ -99,6 +102,23 @@
private var actionIdToLabel = SparseArrayCompat<SparseArrayCompat<CharSequence>>()
private var labelToActionId = SparseArrayCompat<Map<CharSequence, Int>>()
+ private class SemanticsNodeCopy(
+ semanticsNode: SemanticsNode
+ ) {
+ val config = semanticsNode.config
+ val children: MutableSet<Int> = mutableSetOf()
+
+ init {
+ semanticsNode.children.fastForEach { child ->
+ children.add(child.id)
+ }
+ }
+ }
+
+ private var semanticsNodes: MutableMap<Int, SemanticsNodeCopy> = mutableMapOf()
+ private var semanticsRoot = SemanticsNodeCopy(view.semanticsOwner.rootSemanticsNode)
+ private var checkingForSemanticsChanges = false
+
fun createNodeInfo(virtualViewId: Int):
AccessibilityNodeInfoCompat {
val info: AccessibilityNodeInfoCompat = AccessibilityNodeInfoCompat.obtain()
@@ -131,7 +151,7 @@
// TODO(b/151240295): Should we have widgets class name?
info.className = ClassName
- info.setPackageName(view.getContext().getPackageName())
+ info.packageName = view.context.packageName
try {
info.setBoundsInScreen(
android.graphics.Rect(
@@ -153,13 +173,13 @@
// Manage internal accessibility focus state.
if (focusedVirtualViewId == virtualViewId) {
- info.setAccessibilityFocused(true)
+ info.isAccessibilityFocused = true
info.addAction(
AccessibilityNodeInfoCompat.AccessibilityActionCompat
.ACTION_CLEAR_ACCESSIBILITY_FOCUS
)
} else {
- info.setAccessibilityFocused(false)
+ info.isAccessibilityFocused = false
info.addAction(
AccessibilityNodeInfoCompat.AccessibilityActionCompat
.ACTION_ACCESSIBILITY_FOCUS
@@ -212,7 +232,7 @@
)
}
- var rangeInfo =
+ val rangeInfo =
semanticsNode.config.getOrNull(SemanticsProperties.AccessibilityRangeInfo)
if (rangeInfo != null) {
info.rangeInfo = AccessibilityNodeInfoCompat.RangeInfoCompat.obtain(
@@ -222,26 +242,26 @@
}
if (semanticsNode.config.contains(CustomActions)) {
- var customActions = semanticsNode.config[CustomActions]
+ val customActions = semanticsNode.config[CustomActions]
if (customActions.size >= AccessibilityActionsResourceIds.size) {
throw IllegalStateException(
"Can't have more than " +
"${AccessibilityActionsResourceIds.size} custom actions for one widget"
)
}
- var currentActionIdToLabel = SparseArrayCompat<CharSequence>()
- var currentLabelToActionId = mutableMapOf<CharSequence, Int>()
+ val currentActionIdToLabel = SparseArrayCompat<CharSequence>()
+ val currentLabelToActionId = mutableMapOf<CharSequence, Int>()
// If this virtual node had custom action id assignment before, we try to keep the id
// unchanged for the same action (identified by action label). This way, we can
// minimize the influence of custom action change between custom actions are
// presented to the user and actually performed.
if (labelToActionId.containsKey(virtualViewId)) {
- var oldLabelToActionId = labelToActionId[virtualViewId]
- var availableIds = AccessibilityActionsResourceIds.toMutableList()
- var unassignedActions = mutableListOf<CustomAccessibilityAction>()
+ val oldLabelToActionId = labelToActionId[virtualViewId]
+ val availableIds = AccessibilityActionsResourceIds.toMutableList()
+ val unassignedActions = mutableListOf<CustomAccessibilityAction>()
for (action in customActions) {
if (oldLabelToActionId!!.contains(action.label)) {
- var actionId = oldLabelToActionId[action.label]
+ val actionId = oldLabelToActionId[action.label]
currentActionIdToLabel.put(actionId!!, action.label)
currentLabelToActionId[action.label] = actionId
availableIds.remove(actionId)
@@ -255,7 +275,7 @@
}
}
for ((index, action) in unassignedActions.withIndex()) {
- var actionId = availableIds[index]
+ val actionId = availableIds[index]
currentActionIdToLabel.put(actionId, action.label)
currentLabelToActionId[action.label] = actionId
info.addAction(
@@ -266,7 +286,7 @@
}
} else {
for ((index, action) in customActions.withIndex()) {
- var actionId = AccessibilityActionsResourceIds[index]
+ val actionId = AccessibilityActionsResourceIds[index]
currentActionIdToLabel.put(actionId, action.label)
currentLabelToActionId[action.label] = actionId
info.addAction(
@@ -305,8 +325,9 @@
* @return Whether this virtual view actually took accessibility focus.
*/
private fun requestAccessibilityFocus(virtualViewId: Int): Boolean {
- if (!accessibilityManager.isEnabled() ||
- !accessibilityManager.isTouchExplorationEnabled()) {
+ if (!accessibilityManager.isEnabled ||
+ !accessibilityManager.isTouchExplorationEnabled
+ ) {
return false
}
// TODO: Check virtual view visibility.
@@ -343,9 +364,9 @@
* You should call this method after performing a user action that normally
* fires an accessibility event, such as clicking on an item.
*
- * <pre>public void performItemClick(T item) {
+ * <pre>public performItemClick(T item) {
* ...
- * sendEventForVirtualViewId(item.id, AccessibilityEvent.TYPE_VIEW_CLICKED)
+ * sendEventForVirtualView(item.id, AccessibilityEvent.TYPE_VIEW_CLICKED)
* }
* </pre>
*
@@ -355,13 +376,13 @@
* @param contentDescription Content description of this event.
* @return true if the event was sent successfully.
*/
- fun sendEventForVirtualView(
+ private fun sendEventForVirtualView(
virtualViewId: Int,
eventType: Int,
- contentChangeType: Int?,
- contentDescription: CharSequence?
+ contentChangeType: Int? = null,
+ contentDescription: CharSequence? = null
): Boolean {
- if ((virtualViewId == InvalidId) || !accessibilityManager.isEnabled()) {
+ if ((virtualViewId == InvalidId) || !accessibilityManager.isEnabled) {
return false
}
@@ -374,6 +395,7 @@
if (contentDescription != null) {
event.contentDescription = contentDescription
}
+
return parent.requestSendAccessibilityEvent(view, event)
}
@@ -393,7 +415,7 @@
event.className = ClassName
// Don't allow the client to override these properties.
- event.packageName = view.getContext().getPackageName()
+ event.packageName = view.context.packageName
event.setSource(view, virtualViewId)
return event
@@ -426,7 +448,7 @@
action: Int,
arguments: Bundle?
): Boolean {
- var node: SemanticsNode
+ val node: SemanticsNode
if (virtualViewId == AccessibilityNodeProviderCompat.HOST_VIEW_ID) {
node = view.semanticsOwner.rootSemanticsNode
} else {
@@ -465,13 +487,17 @@
}
android.R.id.accessibilityActionSetProgress -> {
if (arguments == null || !arguments.containsKey(
- AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE)) {
+ AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE
+ )
+ ) {
return false
}
return if (node.canPerformAction(SemanticsActions.SetProgress)) {
node.config[SemanticsActions.SetProgress].action(
arguments.getFloat(
- AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE))
+ AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE
+ )
+ )
} else {
false
}
@@ -515,7 +541,7 @@
return false
}
- when (event.getAction()) {
+ when (event.action) {
MotionEvent.ACTION_HOVER_MOVE, MotionEvent.ACTION_HOVER_ENTER -> {
val virtualViewId: Int = getVirtualViewAt(event.getX(), event.getY())
updateHoveredVirtualView(virtualViewId)
@@ -535,8 +561,8 @@
}
private fun getVirtualViewAt(x: Float, y: Float): Int {
- var node = view.semanticsOwner.rootSemanticsNode
- var id = findVirtualViewAt(x + node.globalBounds.left,
+ val node = view.semanticsOwner.rootSemanticsNode
+ val id = findVirtualViewAt(x + node.globalBounds.left,
y + node.globalBounds.top, node)
if (id == node.id) {
return AccessibilityNodeProviderCompat.HOST_VIEW_ID
@@ -547,7 +573,7 @@
// TODO(b/151729467): compose accessibility getVirtualViewAt needs to be more efficient
private fun findVirtualViewAt(x: Float, y: Float, node: SemanticsNode): Int {
node.children.fastForEach {
- var id = findVirtualViewAt(x, y, it)
+ val id = findVirtualViewAt(x, y, it)
if (id != InvalidId) {
return id
}
@@ -620,6 +646,110 @@
// TODO (in a separate cl): Called when the SemanticsNode with id semanticsNodeId disappears.
// fun clearNode(semanticsNodeId: Int) { // clear the actionIdToId and labelToActionId nodes }
+ internal fun onSemanticsChange() {
+ if (accessibilityManager.isEnabled && !checkingForSemanticsChanges) {
+ checkingForSemanticsChanges = true
+ handler.post {
+ checkForSemanticsChanges()
+ checkingForSemanticsChanges = false
+ }
+ }
+ }
+
+ private fun checkForSemanticsChanges() {
+ val newSemanticsNodes = view.semanticsOwner.getAllSemanticsNodesToMap()
+
+ // Structural change
+ sendSemanticsStructureChangeEvents(view.semanticsOwner.rootSemanticsNode, semanticsRoot)
+
+ // Property change
+ sendSemanticsPropertyChangeEvents(newSemanticsNodes)
+
+ // Update the cache
+ semanticsNodes.clear()
+ for (entry in newSemanticsNodes.entries) {
+ semanticsNodes[entry.key] = SemanticsNodeCopy(entry.value)
+ }
+ semanticsRoot = SemanticsNodeCopy(view.semanticsOwner.rootSemanticsNode)
+ }
+
+ private fun sendSemanticsPropertyChangeEvents(newSemanticsNodes: Map<Int, SemanticsNode>) {
+ for (id in newSemanticsNodes.keys) {
+ if (!semanticsNodes.contains(id)) {
+ continue
+ }
+
+ // We do doing this search because the new configuration is set as a whole, so we
+ // can't indicate which property is changed when setting the new configuration.
+ val newNode = newSemanticsNodes[id]
+ val oldNode = semanticsNodes[id]
+ for (entry in newNode!!.config) {
+ if (entry.value == oldNode!!.config.getOrNull(entry.key)) {
+ continue
+ }
+ when (entry.key) {
+ // we are in aosp, so can't use the state description yet.
+ SemanticsProperties.AccessibilityValue,
+ SemanticsProperties.AccessibilityLabel ->
+ sendEventForVirtualView(
+ semanticsNodeIdToAccessibilityVirtualNodeId(id),
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION,
+ entry.value as CharSequence
+ )
+ else -> {
+ // TODO(b/151840490) send the correct events when property changes
+ }
+ }
+ }
+ }
+ }
+
+ private fun sendSemanticsStructureChangeEvents(
+ newNode: SemanticsNode,
+ oldNode: SemanticsNodeCopy
+ ) {
+ val newChildren: MutableSet<Int> = mutableSetOf()
+
+ // If any child is added, clear the subtree rooted at this node and return.
+ newNode.children.fastForEach { child ->
+ if (!oldNode.children.contains(child.id)) {
+ sendEventForVirtualView(
+ semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
+ null
+ )
+ return
+ }
+ newChildren.add(child.id)
+ }
+
+ // If any child is deleted, clear the subtree rooted at this node and return.
+ for (child in oldNode.children) {
+ if (!newChildren.contains(child)) {
+ sendEventForVirtualView(
+ semanticsNodeIdToAccessibilityVirtualNodeId(newNode.id),
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE,
+ null
+ )
+ return
+ }
+ }
+
+ newNode.children.fastForEach { child ->
+ sendSemanticsStructureChangeEvents(child, semanticsNodes[child.id]!!)
+ }
+ }
+
+ private fun semanticsNodeIdToAccessibilityVirtualNodeId(id: Int): Int {
+ if (id == view.semanticsOwner.rootSemanticsNode.id) {
+ return AccessibilityNodeProviderCompat.HOST_VIEW_ID
+ }
+ return id
+ }
+
inner class MyNodeProvider() : AccessibilityNodeProviderCompat() {
override fun createAccessibilityNodeInfo(virtualViewId: Int):
AccessibilityNodeInfoCompat? {
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
index 66dec2d..d55e4b3 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
@@ -27,8 +27,8 @@
* [LayoutNodeWrapper] with default implementations for methods.
*/
internal open class DelegatingLayoutNodeWrapper<T : Modifier.Element>(
- override val wrapped: LayoutNodeWrapper,
- val modifier: T
+ override var wrapped: LayoutNodeWrapper,
+ open var modifier: T
) : LayoutNodeWrapper(wrapped.layoutNode) {
override val providedAlignmentLines: Set<AlignmentLine>
get() = wrapped.providedAlignmentLines
@@ -39,10 +39,27 @@
override val measureScope: MeasureScope get() = wrapped.measureScope
+ /**
+ * Indicates that this modifier is used in [wrappedBy] also.
+ */
+ var isChained = false
+
init {
wrapped.wrappedBy = this
}
+ /**
+ * Sets the modifier instance to the new modifier. [modifier] must be the
+ * same type as the current modifier.
+ */
+ fun setModifierTo(modifier: Modifier.Element) {
+ if (modifier !== this.modifier) {
+ require(modifier.javaClass == this.modifier.javaClass)
+ @Suppress("UNCHECKED_CAST")
+ this.modifier = modifier as T
+ }
+ }
+
override fun draw(canvas: Canvas) {
withPositionTranslation(canvas) {
wrapped.draw(canvas)
@@ -135,13 +152,11 @@
override val parentData: Any? get() = wrapped.parentData
override fun attach() {
- wrapped.attach()
_isAttached = true
}
override fun detach() {
_isAttached = false
- wrapped.detach()
}
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt
index fdb1cc0..929b6f5 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/InnerPlaceable.kt
@@ -28,7 +28,6 @@
import androidx.ui.unit.Density
import androidx.ui.unit.IntOffset
import androidx.ui.util.fastAny
-import androidx.ui.util.fastFirstOrNull
import androidx.ui.util.fastForEach
internal class InnerPlaceable(
@@ -58,13 +57,7 @@
}
override val parentData: Any?
- @Suppress("DEPRECATION")
- get() = if (layoutNode.handlesParentData) {
- null
- } else {
- layoutNode.children
- .fastFirstOrNull { it.parentData != null }?.parentData
- }
+ get() = null
override fun findPreviousFocusWrapper() = wrappedBy?.findPreviousFocusWrapper()
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt
index 3b96373..9bd3871 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayerWrapper.kt
@@ -34,6 +34,13 @@
// Do not invalidate itself on position change.
override val invalidateLayerOnBoundsChange get() = false
+ override var modifier: DrawLayerModifier
+ get() = super.modifier
+ set(value) {
+ super.modifier = value
+ _layer?.modifier = value
+ }
+
private val invalidateParentLayer: () -> Unit = {
wrappedBy?.findLayer()?.invalidate()
}
@@ -161,4 +168,8 @@
hitPointerInputFilters
)
}
+
+ override fun onModifierChanged() {
+ _layer?.invalidate()
+ }
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt
index 0449125..2b4d393 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Layout.kt
@@ -16,27 +16,26 @@
package androidx.ui.core
-import android.content.Context
import androidx.compose.Composable
+import androidx.compose.ComposableContract
import androidx.compose.Composition
import androidx.compose.CompositionReference
import androidx.compose.ExperimentalComposeApi
import androidx.compose.FrameManager
import androidx.compose.Recomposer
import androidx.compose.Stable
-import androidx.compose.Untracked
import androidx.compose.compositionReference
import androidx.compose.currentComposer
+import androidx.compose.emit
import androidx.compose.onDispose
import androidx.compose.remember
import androidx.ui.core.LayoutNode.LayoutState
+import androidx.ui.node.UiApplier
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
import androidx.ui.unit.IntOffset
import androidx.ui.unit.IntSize
import androidx.ui.util.fastForEach
-import androidx.ui.util.fastMap
-import androidx.ui.util.fastMaxBy
import kotlin.math.max
/**
@@ -164,9 +163,15 @@
measureBlocks: LayoutNode.MeasureBlocks,
modifier: Modifier
) {
- LayoutNode(modifier = currentComposer.materialize(modifier), measureBlocks = measureBlocks) {
- children()
- }
+ val materialized = currentComposer.materialize(modifier)
+ emit<LayoutNode, UiApplier>(
+ ctor = LayoutEmitHelper.constructor,
+ update = {
+ set(materialized, LayoutEmitHelper.setModifier)
+ set(measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+ },
+ children = children
+ )
}
@Composable
@@ -178,42 +183,17 @@
measureBlock: MeasureBlock
) {
val measureBlocks = remember(measureBlock) { MeasuringIntrinsicsMeasureBlocks(measureBlock) }
- LayoutNode(
- modifier = currentComposer.materialize(modifier),
- measureBlocks = measureBlocks,
- canMultiMeasure =
- true
- ) {
- children()
- }
-}
-
-@Composable
-@Deprecated("This composable supports our transition from single child composables to modifiers. " +
- "It should not be used in app code directly.")
-fun PassThroughLayout(
- modifier: Modifier = Modifier,
- children: @Composable () -> Unit
-) {
- val measureBlocks = remember {
- val measureBlock: MeasureBlock = { measurables, constraints, _ ->
- val placeables = measurables.fastMap { it.measure(constraints) }
- val width = placeables.fastMaxBy { it.width }?.width ?: constraints.minWidth
- val height = placeables.fastMaxBy { it.height }?.height ?: constraints.minHeight
- layout(width, height) {
- placeables.fastForEach { it.place(0, 0) }
- }
- }
- MeasuringIntrinsicsMeasureBlocks(measureBlock)
- }
- LayoutNode(
- modifier = currentComposer.materialize(modifier),
- measureBlocks = measureBlocks,
- handlesParentData = false,
- useChildZIndex = true
- ) {
- children()
- }
+ val materialized = currentComposer.materialize(modifier)
+ emit<LayoutNode, UiApplier>(
+ ctor = LayoutEmitHelper.constructor,
+ update = {
+ set(materialized, LayoutEmitHelper.setModifier)
+ set(measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+ @Suppress("DEPRECATION")
+ set(Unit) { this.canMultiMeasure = true }
+ },
+ children = children
+ )
}
/**
@@ -463,7 +443,6 @@
) {
val state = remember { WithConstrainsState() }
state.children = children
- state.context = ContextAmbient.current
// TODO(lmr): refactor these APIs so that recomposer isn't necessary
@OptIn(ExperimentalComposeApi::class)
state.recomposer = currentComposer.recomposer
@@ -471,10 +450,14 @@
// if this code was executed subcomposition must be triggered as well
state.forceRecompose = true
- LayoutNode(
- modifier = currentComposer.materialize(modifier),
- ref = state.nodeRef,
- measureBlocks = state.measureBlocks
+ val materialized = currentComposer.materialize(modifier)
+ emit<LayoutNode, UiApplier>(
+ ctor = LayoutEmitHelper.constructor,
+ update = {
+ set(materialized, LayoutEmitHelper.setModifier)
+ set(state.measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+ set(state.nodeRef, LayoutEmitHelper.setRef)
+ }
)
// if LayoutNode scheduled the remeasuring no further steps are needed - subcomposition
@@ -535,7 +518,6 @@
private class WithConstrainsState {
lateinit var recomposer: Recomposer
var compositionRef: CompositionReference? = null
- lateinit var context: Context
val nodeRef = Ref<LayoutNode>()
var children: @Composable WithConstraintsScope.() -> Unit = { }
var forceRecompose = false
@@ -590,9 +572,13 @@
@OptIn(ExperimentalComposeApi::class)
fun subcompose() {
- // TODO(b/150390669): Review use of @Untracked
+ // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
composition =
- subcomposeInto(context, nodeRef.value!!, recomposer, compositionRef) @Untracked {
+ subcomposeInto(
+ nodeRef.value!!,
+ recomposer,
+ compositionRef
+ ) @ComposableContract(tracked = false) {
scope.children()
}
forceRecompose = false
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt
index f389a47..b8e76fd 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutCoordinates.kt
@@ -72,7 +72,7 @@
/**
* Returns the position of an [alignment line][AlignmentLine],
- * or `null` if the line is not provided.
+ * or [AlignmentLine.Unspecified] if the line is not provided.
*/
operator fun get(line: AlignmentLine): Int
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt
index f792361..e830aa7 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNode.kt
@@ -90,6 +90,12 @@
get() = requireOwner().measureIteration == outerMeasurablePlaceable.measureIteration
/**
+ * A cache of modifiers to be used when setting and reusing previous modifiers.
+ */
+ private var wrapperCache = emptyArray<DelegatingLayoutNodeWrapper<*>?>()
+ private var wrapperCacheCount = 0
+
+ /**
* Inserts a child [LayoutNode] at a particular index. If this LayoutNode [owner] is not `null`
* then [instance] will become [attach]ed also. [instance] must have a `null` [parent].
*/
@@ -179,7 +185,7 @@
requestRemeasure()
parent?.requestRemeasure()
- outerLayoutNodeWrapper.attach()
+ forEachDelegate { it.attach() }
onAttach?.invoke(owner)
}
@@ -198,7 +204,7 @@
alignmentLinesQueryOwner = null
alignmentUsageByParent = UsageByParent.NotUsed
onDetach?.invoke(owner)
- outerLayoutNodeWrapper.detach()
+ forEachDelegate { it.detach() }
if (outerSemantics != null) {
owner.onSemanticsChange()
@@ -465,20 +471,7 @@
* this features.
*/
internal val zIndex: Float
- get() {
- @Suppress("DEPRECATION")
- return if (useChildZIndex) {
- // While some temporary components for adding semantics have to add
- // PassThroughLayout it breaks zIndex calculation via adding extra layout layer.
- // To workaround it we use the zIndex of the first child of PassThroughLayout
- children.firstOrNull()?.zIndex ?: 0f
- } else {
- outerZIndexModifier?.zIndex ?: 0f
- }
- }
-
- @Deprecated("To be removed when we remove PassThroughLayout")
- internal var useChildZIndex = false
+ get() = outerZIndexModifier?.zIndex ?: 0f
/**
* The outermost ZIndexModifier in the modifier chain or `null` if there are no
@@ -507,6 +500,8 @@
if (value == field) return
field = value
+ copyWrappersToCache()
+
// Rebuild layoutNodeWrapper
val oldOuterWrapper = outerMeasurablePlaceable.outerWrapper
if (outerSemantics != null && isAttached()) {
@@ -517,65 +512,95 @@
onChildPositionedCallbacks.clear()
outerZIndexModifier = null
innerLayerWrapper = null
+
+ // Create a new chain of LayoutNodeWrappers, reusing existing ones from wrappers
+ // when possible.
val outerWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
var wrapper = toWrap
- // The order in which the following blocks occur matters. For example, the
- // DrawModifier block should be before the LayoutModifier block so that a Modifier
- // that implements both DrawModifier and LayoutModifier will have it's draw bounds
- // reflect the dimensions defined by the LayoutModifier.
if (mod is OnPositionedModifier) {
onPositionedCallbacks += mod
}
if (mod is OnChildPositionedModifier) {
onChildPositionedCallbacks += mod
}
- if (mod is DrawModifier) {
- wrapper = ModifiedDrawNode(wrapper, mod)
- }
- if (mod is DrawLayerModifier) {
- val layerWrapper = LayerWrapper(wrapper, mod)
- wrapper = layerWrapper
- if (innerLayerWrapper == null) {
- innerLayerWrapper = layerWrapper
- }
- }
- if (mod is FocusModifier) {
- require(mod is FocusModifierImpl)
- wrapper = ModifiedFocusNode(wrapper, mod).also { mod.focusNode = it }
- }
- if (mod is KeyInputModifier) {
- wrapper = ModifiedKeyInputNode(wrapper, mod).also { mod.keyInputNode = it }
- }
- if (mod is PointerInputModifier) {
- wrapper = PointerInputDelegatingWrapper(wrapper, mod)
- }
- if (mod is LayoutModifier) {
- wrapper = ModifiedLayoutNode(wrapper, mod)
- }
- if (mod is ParentDataModifier) {
- wrapper = ModifiedParentDataNode(wrapper, mod)
- }
- if (mod is SemanticsModifier) {
- wrapper = SemanticsWrapper(wrapper, mod)
- if (isAttached()) {
- owner!!.onSemanticsChange()
- }
- }
if (mod is ZIndexModifier) {
outerZIndexModifier = mod
}
+
+ val delegate = reuseLayoutNodeWrapper(mod, toWrap)
+ if (delegate != null) {
+ wrapper = delegate
+ } else {
+ // The order in which the following blocks occur matters. For example, the
+ // DrawModifier block should be before the LayoutModifier block so that a
+ // Modifier that implements both DrawModifier and LayoutModifier will have
+ // it's draw bounds reflect the dimensions defined by the LayoutModifier.
+ if (mod is DrawModifier) {
+ wrapper = ModifiedDrawNode(wrapper, mod)
+ }
+ if (mod is DrawLayerModifier) {
+ val layerWrapper = LayerWrapper(wrapper, mod).assignChained(toWrap)
+ wrapper = layerWrapper
+ if (innerLayerWrapper == null) {
+ innerLayerWrapper = layerWrapper
+ }
+ }
+ if (mod is FocusModifier) {
+ require(mod is FocusModifierImpl)
+ wrapper = ModifiedFocusNode(wrapper, mod).also { mod.focusNode = it }
+ .assignChained(toWrap)
+ }
+ if (mod is KeyInputModifier) {
+ wrapper = ModifiedKeyInputNode(wrapper, mod).also { mod.keyInputNode = it }
+ .assignChained(toWrap)
+ }
+ if (mod is PointerInputModifier) {
+ wrapper = PointerInputDelegatingWrapper(wrapper, mod).assignChained(toWrap)
+ }
+ if (mod is LayoutModifier) {
+ wrapper = ModifiedLayoutNode(wrapper, mod).assignChained(toWrap)
+ }
+ if (mod is ParentDataModifier) {
+ wrapper = ModifiedParentDataNode(wrapper, mod).assignChained(toWrap)
+ }
+ if (mod is SemanticsModifier) {
+ wrapper = SemanticsWrapper(wrapper, mod).assignChained(toWrap)
+ }
+ }
wrapper
}
+
outerWrapper.wrappedBy = parent?.innerLayoutNodeWrapper
outerMeasurablePlaceable.outerWrapper = outerWrapper
+
+ if (isAttached()) {
+ // call detach() on all removed LayoutNodeWrappers
+ for (i in 0 until wrapperCacheCount) {
+ wrapperCache[i]?.detach()
+ }
+
+ // attach() all new LayoutNodeWrappers
+ forEachDelegate {
+ if (!it.isAttached) {
+ it.attach()
+ }
+ }
+ }
+ for (i in 0 until wrapperCacheCount) {
+ wrapperCache[i] = null
+ }
+ wrapperCacheCount = 0
+
+ // call onModifierChanged() on all LayoutNodeWrappers
+ forEachDelegate { it.onModifierChanged() }
+
// Optimize the case where the layout itself is not modified. A common reason for
// this is if no wrapping actually occurs above because no LayoutModifiers are
// present in the modifier chain.
- if (oldOuterWrapper != outerWrapper) {
- oldOuterWrapper.detach()
+ if (oldOuterWrapper != innerLayoutNodeWrapper ||
+ outerWrapper != innerLayoutNodeWrapper) {
requestRemeasure()
parent?.requestRelayout()
- outerWrapper.attach()
} else if (layoutState == Ready && addedCallback) {
// We need to notify the callbacks of a change in position since there's
// a new one.
@@ -584,12 +609,6 @@
owner?.onInvalidate(this)
}
- @Deprecated(
- "Temporary API to support our transition from single child composables to modifiers."
- )
- // TODO(popam): remove this
- var handlesParentData: Boolean = true
-
/**
* Coordinates of just the contents of the LayoutNode, after being affected by all modifiers.
*/
@@ -893,9 +912,7 @@
*/
fun getModifierInfo(): List<ModifierInfo> {
val infoList = mutableListOf<ModifierInfo>()
- var wrapper = outerLayoutNodeWrapper
-
- while (wrapper != innerLayoutNodeWrapper) {
+ forEachDelegate { wrapper ->
val info = if (wrapper is LayerWrapper) {
ModifierInfo(wrapper.modifier, wrapper, wrapper.layer)
} else {
@@ -903,11 +920,95 @@
ModifierInfo(wrapper.modifier, wrapper)
}
infoList += info
- wrapper = wrapper.wrapped!!
}
return infoList
}
+ /**
+ * Reuses a [DelegatingLayoutNodeWrapper] from [wrapperCache] if one matches the class
+ * type of [modifier]. This walks backward through the [wrapperCache] and
+ * extracts all [DelegatingLayoutNodeWrapper]s that are
+ * [chained][DelegatingLayoutNodeWrapper.isChained] together.
+ * If none can be reused, `null` is returned.
+ */
+ private fun reuseLayoutNodeWrapper(
+ modifier: Modifier.Element,
+ wrapper: LayoutNodeWrapper
+ ): DelegatingLayoutNodeWrapper<*>? {
+ if (wrapperCacheCount == 0) {
+ return null
+ }
+ val index = lastMatchingModifierIndex(modifier)
+
+ if (index < 0) {
+ return null
+ }
+
+ val endWrapper = removeFromWrapperCache(index)
+ var startWrapper = endWrapper
+ var chainedIndex = index
+ startWrapper.setModifierTo(modifier)
+ if (innerLayerWrapper == null && startWrapper is LayerWrapper) {
+ innerLayerWrapper = startWrapper
+ }
+
+ while (startWrapper.isChained) {
+ chainedIndex--
+ startWrapper = removeFromWrapperCache(chainedIndex)
+ startWrapper.setModifierTo(modifier)
+ if (innerLayerWrapper == null && startWrapper is LayerWrapper) {
+ innerLayerWrapper = startWrapper
+ }
+ }
+
+ endWrapper.wrapped = wrapper
+ wrapper.wrappedBy = endWrapper
+ return startWrapper
+ }
+
+ private fun lastMatchingModifierIndex(modifier: Modifier): Int {
+ var index = wrapperCacheCount - 1
+ while (index >= 0) {
+ val wrapper = wrapperCache[index]
+ if (wrapper != null && (wrapper.modifier === modifier ||
+ wrapper.modifier.javaClass == modifier.javaClass)) {
+ return index
+ }
+ index--
+ }
+ return -1
+ }
+
+ private fun removeFromWrapperCache(index: Int): DelegatingLayoutNodeWrapper<*> {
+ val wrapper = wrapperCache[index]!!
+ wrapperCache[index] = null
+ if (index == wrapperCacheCount - 1) {
+ wrapperCacheCount--
+ }
+ return wrapper
+ }
+
+ /**
+ * Copies all [DelegatingLayoutNodeWrapper]s currently in use and returns them in a new
+ * Array.
+ */
+ private fun copyWrappersToCache() {
+ // first count them:
+ var count = 0
+ forEachDelegate { count++ }
+ if (count == 0) {
+ return
+ }
+ if (wrapperCache.size < count) {
+ wrapperCache = arrayOfNulls(count)
+ }
+ wrapperCacheCount = count
+ var i = 0
+ forEachDelegate {
+ wrapperCache[i++] = it as DelegatingLayoutNodeWrapper<*>
+ }
+ }
+
// Delegation from Measurable to measurableAndPlaceable
override fun measure(constraints: Constraints, layoutDirection: LayoutDirection) =
outerMeasurablePlaceable.measure(constraints, layoutDirection)
@@ -934,6 +1035,18 @@
override fun maxIntrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int =
outerMeasurablePlaceable.maxIntrinsicHeight(width, layoutDirection)
+ /**
+ * Calls [block] on all [DelegatingLayoutNodeWrapper]s in the LayoutNodeWrapper chain.
+ */
+ private inline fun forEachDelegate(block: (LayoutNodeWrapper) -> Unit) {
+ var delegate = outerLayoutNodeWrapper
+ val inner = innerLayoutNodeWrapper
+ while (delegate != inner) {
+ block(delegate)
+ delegate = delegate.wrapped!!
+ }
+ }
+
internal companion object {
private val ErrorMeasureBlocks = object : NoIntrinsicsMeasureBlocks(
error = "Undefined intrinsics block and it is required"
@@ -982,6 +1095,17 @@
}
/**
+ * Object of pre-allocated lambdas used to make emits to LayoutNodes allocation-less.
+ */
+internal object LayoutEmitHelper {
+ val constructor: () -> LayoutNode = { LayoutNode() }
+ val setModifier: LayoutNode.(Modifier) -> Unit = { this.modifier = it }
+ val setMeasureBlocks: LayoutNode.(LayoutNode.MeasureBlocks) -> Unit =
+ { this.measureBlocks = it }
+ val setRef: LayoutNode.(Ref<LayoutNode>) -> Unit = { this.ref = it }
+}
+
+/**
* Comparator allowing to sort nodes by zIndex
*/
private val ZIndexComparator = Comparator<LayoutNode> { node1, node2 ->
@@ -1075,3 +1199,20 @@
override val layoutDirection: LayoutDirection
get() = wrapped!!.measureScope.layoutDirection
}
+
+/**
+ * Sets [DelegatingLayoutNodeWrapper#isChained] to `true` of the [wrapped] when it
+ * is part of a chain of LayoutNodes for the same modifier.
+ *
+ * @param originalWrapper The LayoutNodeWrapper that the modifier chain should be wrapping.
+ */
+@Suppress("NOTHING_TO_INLINE")
+private inline fun <T : DelegatingLayoutNodeWrapper<*>> T.assignChained(
+ originalWrapper: LayoutNodeWrapper
+): T {
+ if (originalWrapper !== wrapped) {
+ var wrapper = wrapped as DelegatingLayoutNodeWrapper<*>
+ wrapper.isChained = true
+ }
+ return this
+}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt
index 0a761c0..7e56b29 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutNodeWrapper.kt
@@ -376,6 +376,12 @@
*/
abstract fun findLastKeyInputWrapper(): ModifiedKeyInputNode?
+ /**
+ * Called when [LayoutNode.modifier] has changed and all the LayoutNodeWrappers have been
+ * configured.
+ */
+ open fun onModifierChanged() {}
+
internal companion object {
const val ExpectAttachedLayoutCoordinates = "LayoutCoordinate operations are only valid " +
"when isAttached is true"
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt
index 9d4e4d0..753df72 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/LayoutTreeConsistencyChecker.kt
@@ -57,10 +57,16 @@
// `onRequestMeasure` will be called for all items in `postponedMeasureRequests`
return true
}
- if (layoutState == LayoutState.NeedsRemeasure ||
- layoutState == LayoutState.NeedsRelayout) {
- // remeasure or relayout is scheduled
- return relayoutNodes.contains(this)
+ // remeasure or relayout is scheduled
+ val parentLayoutState = parent?.layoutState
+ if (layoutState == LayoutState.NeedsRemeasure) {
+ return relayoutNodes.contains(this) ||
+ parentLayoutState == LayoutState.NeedsRemeasure
+ }
+ if (layoutState == LayoutState.NeedsRelayout) {
+ return relayoutNodes.contains(this) ||
+ parentLayoutState == LayoutState.NeedsRemeasure ||
+ parentLayoutState == LayoutState.NeedsRelayout
}
}
return true
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt
index 6da999b..4b685eb 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/MeasureAndLayoutDelegate.kt
@@ -129,7 +129,10 @@
} else {
layoutNode.layoutState = NeedsRemeasure
if (layoutNode.isPlaced || layoutNode.canAffectPlacedParent) {
- relayoutNodes.add(layoutNode)
+ val parentLayoutState = layoutNode.parent?.layoutState
+ if (parentLayoutState != NeedsRemeasure) {
+ relayoutNodes.add(layoutNode)
+ }
}
}
!duringMeasureLayout
@@ -152,7 +155,10 @@
Ready -> {
layoutNode.layoutState = NeedsRelayout
if (layoutNode.isPlaced) {
- relayoutNodes.add(layoutNode)
+ val parentLayoutState = layoutNode.parent?.layoutState
+ if (parentLayoutState != NeedsRemeasure && parentLayoutState != NeedsRelayout) {
+ relayoutNodes.add(layoutNode)
+ }
}
!duringMeasureLayout
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt
index 5abf9d5..aca0bc1 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ModifiedLayoutNode.kt
@@ -22,40 +22,40 @@
import androidx.ui.graphics.PaintingStyle
internal class ModifiedLayoutNode(
wrapped: LayoutNodeWrapper,
- private val layoutModifier: LayoutModifier
-) : DelegatingLayoutNodeWrapper<LayoutModifier>(wrapped, layoutModifier) {
+ modifier: LayoutModifier
+) : DelegatingLayoutNodeWrapper<LayoutModifier>(wrapped, modifier) {
override val measureScope = ModifierMeasureScope()
override fun performMeasure(
constraints: Constraints,
layoutDirection: LayoutDirection
- ): Placeable = with(layoutModifier) {
+ ): Placeable = with(modifier) {
measureScope.layoutDirection = layoutDirection
measureResult = measureScope.measure(wrapped, constraints, layoutDirection)
this@ModifiedLayoutNode
}
override fun minIntrinsicWidth(height: Int, layoutDirection: LayoutDirection): Int =
- with(layoutModifier) {
+ with(modifier) {
measureScope.layoutDirection = layoutDirection
measureScope.minIntrinsicWidth(wrapped, height, layoutDirection)
}
override fun maxIntrinsicWidth(height: Int, layoutDirection: LayoutDirection): Int =
- with(layoutModifier) {
+ with(modifier) {
measureScope.layoutDirection = layoutDirection
measureScope.maxIntrinsicWidth(wrapped, height, layoutDirection)
}
override fun minIntrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int =
- with(layoutModifier) {
+ with(modifier) {
measureScope.layoutDirection = layoutDirection
measureScope.minIntrinsicHeight(wrapped, width, layoutDirection)
}
override fun maxIntrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int =
- with(layoutModifier) {
+ with(modifier) {
measureScope.layoutDirection = layoutDirection
measureScope.maxIntrinsicHeight(wrapped, width, layoutDirection)
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt
index 6190494..2001b81 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/OwnedLayer.kt
@@ -33,6 +33,11 @@
val layerId: Long
/**
+ * The DrawLayerModifier used in this layer.
+ */
+ var modifier: DrawLayerModifier
+
+ /**
* Reads the [DrawLayerModifier] and dirties the layer so that it will be redrawn.
*/
fun updateLayerProperties()
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt
index 46d2a7a..253f6a7 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Popup.kt
@@ -32,7 +32,6 @@
import androidx.compose.ambientOf
import androidx.compose.currentComposer
import androidx.compose.emptyContent
-import androidx.compose.escapeCompose
import androidx.compose.onCommit
import androidx.compose.onDispose
import androidx.compose.remember
@@ -161,16 +160,14 @@
val popupPositionProperties = remember { PopupPositionProperties() }
val popupLayout = remember(isFocusable) {
- escapeCompose {
- PopupLayout(
- composeView = view,
- popupIsFocusable = isFocusable,
- onDismissRequest = onDismissRequest,
- popupPositionProperties = popupPositionProperties,
- popupPositionProvider = popupPositionProvider,
- testTag = providedTestTag
- )
- }
+ PopupLayout(
+ composeView = view,
+ popupIsFocusable = isFocusable,
+ onDismissRequest = onDismissRequest,
+ popupPositionProperties = popupPositionProperties,
+ popupPositionProvider = popupPositionProvider,
+ testTag = providedTestTag
+ )
}
popupLayout.popupPositionProvider = popupPositionProvider
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt
index f032b4c..aeb05dc 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/RenderNodeLayer.kt
@@ -32,7 +32,7 @@
@TargetApi(29)
internal class RenderNodeLayer(
val ownerView: AndroidComposeView,
- val drawLayerModifier: DrawLayerModifier,
+ drawLayerModifier: DrawLayerModifier,
val drawBlock: (Canvas) -> Unit,
val invalidateParentLayer: () -> Unit
) : OwnedLayer {
@@ -61,22 +61,30 @@
override val layerId: Long
get() = renderNode.uniqueId
+ override var modifier: DrawLayerModifier = drawLayerModifier
+ set(value) {
+ if (field !== value) {
+ field = value
+ updateLayerProperties()
+ }
+ }
+
override fun updateLayerProperties() {
- transformOrigin = drawLayerModifier.transformOrigin
+ transformOrigin = modifier.transformOrigin
val wasClippingManually = renderNode.clipToOutline && outlineResolver.clipPath != null
- renderNode.scaleX = drawLayerModifier.scaleX
- renderNode.scaleY = drawLayerModifier.scaleY
- renderNode.alpha = drawLayerModifier.alpha
- renderNode.translationX = drawLayerModifier.translationX
- renderNode.translationY = drawLayerModifier.translationY
- renderNode.elevation = drawLayerModifier.shadowElevation
- renderNode.rotationZ = drawLayerModifier.rotationZ
- renderNode.rotationX = drawLayerModifier.rotationX
- renderNode.rotationY = drawLayerModifier.rotationY
+ renderNode.scaleX = modifier.scaleX
+ renderNode.scaleY = modifier.scaleY
+ renderNode.alpha = modifier.alpha
+ renderNode.translationX = modifier.translationX
+ renderNode.translationY = modifier.translationY
+ renderNode.elevation = modifier.shadowElevation
+ renderNode.rotationZ = modifier.rotationZ
+ renderNode.rotationX = modifier.rotationX
+ renderNode.rotationY = modifier.rotationY
renderNode.pivotX = transformOrigin.pivotFractionX * renderNode.width
renderNode.pivotY = transformOrigin.pivotFractionY * renderNode.height
- val shape = drawLayerModifier.shape
- val clip = drawLayerModifier.clip
+ val shape = modifier.shape
+ val clip = modifier.clip
renderNode.clipToOutline = clip && shape !== RectangleShape
renderNode.clipToBounds = clip && shape === RectangleShape
val shapeChanged = outlineResolver.update(
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt
index 25532ba..084285b 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/TestTag.kt
@@ -16,27 +16,12 @@
package androidx.ui.core
-import androidx.compose.Composable
import androidx.compose.Stable
import androidx.ui.core.semantics.semantics
import androidx.ui.semantics.SemanticsPropertyReceiver
import androidx.ui.semantics.testTag
/**
- * Applies a tag to allow this element to be found in tests.
- *
- * This is a convenience method for a [Semantics] that sets [SemanticsPropertyReceiver.testTag].
- */
-@Composable
-@Deprecated(message = "Use Modifier.testTag instead.")
-fun TestTag(tag: String, children: @Composable () -> Unit) {
- @Suppress("DEPRECATION")
- PassThroughLayout(
- Modifier.semantics(applyToChildLayoutNode = true, properties = { testTag = tag }),
- children)
-}
-
-/**
* Applies a tag to allow modified element to be found in tests.
*
* This is a convenience method for a [semantics] that sets [SemanticsPropertyReceiver.testTag].
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt
index 8a697e6..a158617 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/ViewLayer.kt
@@ -35,7 +35,7 @@
internal class ViewLayer(
val ownerView: AndroidComposeView,
val container: ViewLayerContainer,
- val drawLayerModifier: DrawLayerModifier,
+ drawLayerModifier: DrawLayerModifier,
val drawBlock: (Canvas) -> Unit,
val invalidateParentLayer: () -> Unit
) : View(ownerView.context), OwnedLayer {
@@ -49,6 +49,14 @@
private var drawnWithZ = false
private val canvasHolder = CanvasHolder()
+ override var modifier: DrawLayerModifier = drawLayerModifier
+ set(value) {
+ if (value !== field) {
+ field = value
+ updateLayerProperties()
+ }
+ }
+
/**
* Local copy of the transform origin as DrawLayerModifier can be implemented
* as a model object. Update this field within [updateLayerProperties] and use it
@@ -66,20 +74,20 @@
get() = id.toLong()
override fun updateLayerProperties() {
- this.mTransformOrigin = drawLayerModifier.transformOrigin
- this.scaleX = drawLayerModifier.scaleX
- this.scaleY = drawLayerModifier.scaleY
- this.alpha = drawLayerModifier.alpha
- this.translationX = drawLayerModifier.translationX
- this.translationY = drawLayerModifier.translationY
- this.elevation = drawLayerModifier.shadowElevation
- this.rotation = drawLayerModifier.rotationZ
- this.rotationX = drawLayerModifier.rotationX
- this.rotationY = drawLayerModifier.rotationY
+ this.mTransformOrigin = modifier.transformOrigin
+ this.scaleX = modifier.scaleX
+ this.scaleY = modifier.scaleY
+ this.alpha = modifier.alpha
+ this.translationX = modifier.translationX
+ this.translationY = modifier.translationY
+ this.elevation = modifier.shadowElevation
+ this.rotation = modifier.rotationZ
+ this.rotationX = modifier.rotationX
+ this.rotationY = modifier.rotationY
this.pivotX = mTransformOrigin.pivotFractionX * width
this.pivotY = mTransformOrigin.pivotFractionY * height
- val shape = drawLayerModifier.shape
- val clip = drawLayerModifier.clip
+ val shape = modifier.shape
+ val clip = modifier.clip
this.clipToBounds = clip && shape === RectangleShape
resetClipBounds()
val wasClippingManually = manualClipPath != null
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt
index e7f07d0..b9262c1 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/Wrapper.kt
@@ -16,7 +16,6 @@
package androidx.ui.core
import android.app.Activity
-import android.content.Context
import android.os.Build
import android.view.View
import android.view.ViewGroup
@@ -26,8 +25,10 @@
import androidx.compose.Composable
import androidx.compose.Composition
import androidx.compose.CompositionReference
+import androidx.compose.ExperimentalComposeApi
import androidx.compose.FrameManager
import androidx.compose.InternalComposeApi
+import androidx.compose.Providers
import androidx.compose.Recomposer
import androidx.compose.SlotTable
import androidx.compose.compositionFor
@@ -36,7 +37,7 @@
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.ui.core.selection.SelectionContainer
-import androidx.ui.node.UiComposer
+import androidx.ui.node.UiApplier
import java.util.Collections
import java.util.WeakHashMap
@@ -47,19 +48,24 @@
* @see Composition.dispose
*/
// TODO: Remove this API when View/LayoutNode mixed trees work
+@OptIn(ExperimentalComposeApi::class)
fun ViewGroup.setViewContent(
parent: CompositionReference? = null,
composable: @Composable () -> Unit
): Composition = compositionFor(
- context = context,
- container = this,
- recomposer = Recomposer.current(),
- parent = parent,
- onBeforeFirstComposition = {
+ this,
+ UiApplier(this),
+ Recomposer.current(),
+ parent,
+ onCreated = {
removeAllViews()
}
).apply {
- setContent(composable)
+ setContent {
+ Providers(ContextAmbient provides [email protected]) {
+ composable()
+ }
+ }
}
/**
@@ -87,13 +93,18 @@
// nextFrame() inside recompose() doesn't really start a new frame, but a new subframe
// instead.
@MainThread
+@OptIn(ExperimentalComposeApi::class)
fun subcomposeInto(
- context: Context,
container: LayoutNode,
recomposer: Recomposer,
parent: CompositionReference? = null,
composable: @Composable () -> Unit
-): Composition = compositionFor(context, container, recomposer, parent).apply {
+): Composition = compositionFor(
+ container,
+ UiApplier(container),
+ recomposer,
+ parent
+).apply {
setContent(composable)
}
@@ -107,10 +118,9 @@
@MainThread
fun subcomposeInto(
container: LayoutNode,
- context: Context,
parent: CompositionReference? = null,
composable: @Composable () -> Unit
-): Composition = subcomposeInto(context, container, Recomposer.current(), parent, composable)
+): Composition = subcomposeInto(container, Recomposer.current(), parent, composable)
/**
* Composes the given composable into the given activity. The [content] will become the root view
@@ -134,7 +144,7 @@
?: AndroidOwner(this, this).also {
setContentView(it.view, DefaultLayoutParams)
}
- return doSetContent(this, composeView, recomposer, content)
+ return doSetContent(composeView, recomposer, content)
}
/**
@@ -168,7 +178,7 @@
removeAllViews(); null
}
?: AndroidOwner(context).also { addView(it.view, DefaultLayoutParams) }
- return doSetContent(context, composeView, recomposer, content)
+ return doSetContent(composeView, recomposer, content)
}
/**
@@ -191,7 +201,6 @@
): Composition = setContent(Recomposer.current(), content)
private fun doSetContent(
- context: Context,
owner: AndroidOwner,
recomposer: Recomposer,
content: @Composable () -> Unit
@@ -200,7 +209,8 @@
owner.view.setTag(R.id.inspection_slot_table_set,
Collections.newSetFromMap(WeakHashMap<SlotTable, Boolean>()))
}
- val original = compositionFor(context, owner.root, recomposer)
+ @OptIn(ExperimentalComposeApi::class)
+ val original = compositionFor(owner.root, UiApplier(owner.root), recomposer)
val wrapped = owner.view.getTag(R.id.wrapped_composition_tag)
as? WrappedComposition
?: WrappedComposition(owner, original).also {
@@ -270,23 +280,6 @@
}
}
-@Suppress("NAME_SHADOWING")
-private fun compositionFor(
- context: Context,
- container: Any,
- recomposer: Recomposer,
- parent: CompositionReference? = null,
- onBeforeFirstComposition: (() -> Unit)? = null
-) = compositionFor(
- container = container,
- recomposer = recomposer,
- parent = parent,
- composerFactory = { slotTable, recomposer ->
- onBeforeFirstComposition?.invoke()
- UiComposer(context, container, slotTable, recomposer)
- }
-)
-
private val DefaultLayoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
index 801522c..29ccad2 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilter.kt
@@ -14,9 +14,13 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalPointerInput::class)
+
package androidx.ui.core.gesture
import androidx.compose.remember
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
import androidx.ui.core.DensityAmbient
import androidx.ui.core.Direction
import androidx.ui.core.Modifier
@@ -24,31 +28,46 @@
import androidx.ui.core.PointerInputChange
import androidx.ui.core.changedToUpIgnoreConsumed
import androidx.ui.core.composed
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
import androidx.ui.core.pointerinput.PointerInputFilter
import androidx.ui.core.positionChange
import androidx.ui.geometry.Offset
import androidx.ui.unit.IntSize
/**
- * This gesture filter detects when the average distance change of all pointers surpasses touch
+ * This gesture filter detects when the average distance change of all pointers surpasses the touch
* slop.
*
* The value of touch slop is currently defined internally as the constant [TouchSlop].
*
- * @param onDragSlopExceeded Called when touch slop is exceeded in a supported direction. See
- * [canDrag].
- * @param canDrag Set to limit the directions under which touch slop can be exceeded. Return true
- * if you want a drag to be started due to the touch slop being surpassed in the given [Direction].
- * If [canDrag] is not provided, touch slop will be able to be exceeded in all directions.
+ * Note: [canDrag] and [orientation] interact such that [canDrag] will only be called for
+ * [Direction]s that are included in the given [orientation].
+ *
+ * Note: Changing the value of [orientation] will reset the gesture filter such that it will not
+ * respond to input until new pointers are detected.
+ *
+ * @param onDragSlopExceeded Called when touch slop is exceeded in a supported direction and
+ * orientation.
+ * @param canDrag Set to limit the types of directions under which touch slop can be exceeded.
+ * Return true if you want a drag to be started due to the touch slop being surpassed in the
+ * given [Direction]. If [canDrag] is not provided, touch slop will be able to be exceeded in all
+ * directions.
+ * @param orientation If provided, limits the [Direction]s that scroll slop can be exceeded in to
+ * those that are included in the given orientation and does not consider pointers that are locked
+ * to other orientations.
*/
fun Modifier.dragSlopExceededGestureFilter(
onDragSlopExceeded: () -> Unit,
- canDrag: ((Direction) -> Boolean)? = null
+ canDrag: ((Direction) -> Boolean)? = null,
+ orientation: Orientation? = null
): Modifier = composed {
val touchSlop = with(DensityAmbient.current) { TouchSlop.toPx() }
- val filter = remember { DragSlopExceededGestureFilter(touchSlop) }
- filter.canDrag = canDrag
+ val filter = remember {
+ DragSlopExceededGestureFilter(touchSlop)
+ }
filter.onDragSlopExceeded = onDragSlopExceeded
+ filter.setDraggableData(orientation, canDrag)
PointerInputModifierImpl(filter)
}
@@ -61,80 +80,126 @@
private var dyUnderSlop = 0f
private var passedSlop = false
- var canDrag: ((Direction) -> Boolean)? = null
+ private var canDrag: ((Direction) -> Boolean)? = null
+ private var orientation: Orientation? = null
+
var onDragSlopExceeded: () -> Unit = {}
+ lateinit var scrollOrientationLocker: ScrollOrientationLocker
+ lateinit var customEventDispatcher: CustomEventDispatcher
+
+ fun setDraggableData(orientation: Orientation?, canDrag: ((Direction) -> Boolean)?) {
+ this.orientation = orientation
+ this.canDrag = { direction ->
+ when {
+ orientation == Orientation.Horizontal && direction == Direction.UP -> false
+ orientation == Orientation.Horizontal && direction == Direction.DOWN -> false
+ orientation == Orientation.Vertical && direction == Direction.LEFT -> false
+ orientation == Orientation.Vertical && direction == Direction.RIGHT -> false
+ else -> canDrag?.invoke(direction) ?: true
+ }
+ }
+ }
+
+ override fun onInit(customEventDispatcher: CustomEventDispatcher) {
+ scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+ }
+
override fun onPointerInput(
changes: List<PointerInputChange>,
pass: PointerEventPass,
bounds: IntSize
): List<PointerInputChange> {
- if (!passedSlop &&
- (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown)
- ) {
- // Get current average change.
- val averagePositionChange = getAveragePositionChange(changes)
- val dx = averagePositionChange.x
- val dy = averagePositionChange.y
+ scrollOrientationLocker.onPointerInputSetup(changes, pass)
- // Track changes during postUp and during postDown. This allows for fancy dragging
- // due to a parent being dragged and will likely be removed.
- // TODO(b/157087973): Likely remove this two pass complexity.
- if (pass == PointerEventPass.PostUp) {
- dxForPass = dx
- dyForPass = dy
- dxUnderSlop += dx
- dyUnderSlop += dy
- } else {
- dxUnderSlop += dx - dxForPass
- dyUnderSlop += dy - dyForPass
+ if (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown) {
+
+ // Filter changes for those that we can interact with due to our orientation.
+ val applicableChanges =
+ with(orientation) {
+ if (this != null) {
+ scrollOrientationLocker.getPointersFor(changes, this)
+ } else {
+ changes
+ }
+ }
+
+ if (!passedSlop) {
+
+ // Get current average change.
+ val averagePositionChange = getAveragePositionChange(applicableChanges)
+ val dx = averagePositionChange.x
+ val dy = averagePositionChange.y
+
+ // Track changes during postUp and during postDown. This allows for fancy dragging
+ // due to a parent being dragged and will likely be removed.
+ // TODO(b/157087973): Likely remove this two pass complexity.
+ if (pass == PointerEventPass.PostUp) {
+ dxForPass = dx
+ dyForPass = dy
+ dxUnderSlop += dx
+ dyUnderSlop += dy
+ } else {
+ dxUnderSlop += dx - dxForPass
+ dyUnderSlop += dy - dyForPass
+ }
+
+ // Map the distance to the direction enum for a call to canDrag.
+ val directionX = averagePositionChange.horizontalDirection()
+ val directionY = averagePositionChange.verticalDirection()
+
+ val canDragX = directionX != null && canDrag?.invoke(directionX) ?: true
+ val canDragY = directionY != null && canDrag?.invoke(directionY) ?: true
+
+ val passedSlopX = canDragX && Math.abs(dxUnderSlop) > touchSlop
+ val passedSlopY = canDragY && Math.abs(dyUnderSlop) > touchSlop
+
+ if (passedSlopX || passedSlopY) {
+ passedSlop = true
+ onDragSlopExceeded.invoke()
+ } else {
+ // If we have passed slop in a direction that we can't drag in, we should reset
+ // our tracking back to zero so that a user doesn't have to later scroll the slop
+ // + the extra distance they scrolled in the wrong direction.
+ if (!canDragX &&
+ ((directionX == Direction.LEFT && dxUnderSlop < 0) ||
+ (directionX == Direction.RIGHT && dxUnderSlop > 0))
+ ) {
+ dxUnderSlop = 0f
+ }
+ if (!canDragY &&
+ ((directionY == Direction.UP && dyUnderSlop < 0) ||
+ (directionY == Direction.DOWN && dyUnderSlop > 0))
+ ) {
+ dyUnderSlop = 0f
+ }
+ }
}
- // Map the distance to the direction enum for a call to canDrag.
- val directionX = averagePositionChange.horizontalDirection()
- val directionY = averagePositionChange.verticalDirection()
-
- val canDragX = directionX != null && canDrag?.invoke(directionX) ?: true
- val canDragY = directionY != null && canDrag?.invoke(directionY) ?: true
-
- val passedSlopX = canDragX && Math.abs(dxUnderSlop) > touchSlop
- val passedSlopY = canDragY && Math.abs(dyUnderSlop) > touchSlop
-
- if (passedSlopX || passedSlopY) {
- passedSlop = true
- onDragSlopExceeded.invoke()
- } else {
- // If we have passed slop in a direction that we can't drag in, we should reset
- // our tracking back to zero so that a user doesn't have to later scroll the slop
- // + the extra distance they scrolled in the wrong direction.
- if (!canDragX &&
- ((directionX == Direction.LEFT && dxUnderSlop < 0) ||
- (directionX == Direction.RIGHT && dxUnderSlop > 0))
- ) {
- dxUnderSlop = 0f
- }
- if (!canDragY &&
- ((directionY == Direction.UP && dyUnderSlop < 0) ||
- (directionY == Direction.DOWN && dyUnderSlop > 0))
- ) {
- dyUnderSlop = 0f
- }
+ if (pass == PointerEventPass.PostDown &&
+ changes.all { it.changedToUpIgnoreConsumed() }
+ ) {
+ // On the final pass, check to see if all pointers have changed to up, and if they
+ // have, reset.
+ reset()
}
}
- if (pass == PointerEventPass.PostDown &&
- changes.all { it.changedToUpIgnoreConsumed() }
- ) {
- reset()
- }
+ scrollOrientationLocker.onPointerInputTearDown(changes, pass)
+
return changes
}
override fun onCancel() {
+ scrollOrientationLocker.onCancel()
reset()
}
+ override fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
+ scrollOrientationLocker.onCustomEvent(customEvent, pass)
+ }
+
private fun reset() {
passedSlop = false
dxForPass = 0f
@@ -148,6 +213,10 @@
* Get's the average distance change of all pointers as an Offset.
*/
private fun getAveragePositionChange(changes: List<PointerInputChange>): Offset {
+ if (changes.isEmpty()) {
+ return Offset.Zero
+ }
+
val sum = changes.fold(Offset.Zero) { sum, change ->
sum + change.positionChange()
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ExperimentalPointerInput.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ExperimentalPointerInput.kt
new file mode 100644
index 0000000..8ca6b32
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ExperimentalPointerInput.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.gesture
+
+@RequiresOptIn("This pointer input API is experimental and is likely to change before becoming " +
+ "stable.")
+annotation class ExperimentalPointerInput
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt
index 8484c3a..08a9cee 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/RawDragGestureFilter.kt
@@ -14,9 +14,13 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalPointerInput::class)
+
package androidx.ui.core.gesture
import androidx.compose.remember
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
import androidx.ui.core.Modifier
import androidx.ui.core.PointerEventPass
import androidx.ui.core.PointerId
@@ -28,6 +32,8 @@
import androidx.ui.core.composed
import androidx.ui.core.consumeDownChange
import androidx.ui.core.consumePositionChange
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
import androidx.ui.core.gesture.util.VelocityTracker
import androidx.ui.core.pointerinput.PointerInputFilter
import androidx.ui.core.positionChange
@@ -36,6 +42,9 @@
import androidx.ui.util.fastAny
import androidx.ui.util.fastForEach
+/**
+ * Defines the callbacks associated with dragging.
+ */
interface DragObserver {
/**
@@ -45,10 +54,11 @@
* is null or returns true) and the average distance the pointers have moved are not 0 on
* both the x and y axes.
*
- * @param downPosition The pointer input position of the down event.
+ * Only called if the last called if the most recent call among [onStart], [onStop], and
+ * [onCancel] was [onStop] or [onCancel].
*
- * @see onDrag
- * @see onStop
+ * @param downPosition The average position of all pointer positions when they first touched
+ * down.
*/
fun onStart(downPosition: Offset) {}
@@ -74,16 +84,22 @@
*
* This is called once all pointers have stopped interacting with this DragGestureDetector.
*
- * Only called if the last call between [onStart] and [onStop] was [onStart].
+ * Only called if the last called if the most recent call among [onStart], [onStop], and
+ * [onCancel] was [onStart].
+ *
+ * @param velocity The velocity of the drag in both orientations at the point in time when all
+ * pointers have released the relevant PointerInputFilter. In pixels per second.
*/
fun onStop(velocity: Offset) {}
/**
* Override to be notified when the drag has been cancelled.
*
- * This is called if [onStart] has ben called and then a cancellation event has occurs
- * (for example, due to the gesture detector being removed from the tree) before [onStop] is
- * called.
+ * This is called in response to a cancellation event such as the associated
+ * PointerInputFilter having been removed from the hierarchy.
+ *
+ * Only called if the last called if the most recent call among [onStart], [onStop], and
+ * [onCancel] was [onStart].
*/
fun onCancel() {}
}
@@ -115,29 +131,47 @@
* When multiple pointers are touching the detector, the drag distance is taken as the average of
* all of the pointers.
*
+ * Note: Changing the value of [orientation] will reset the gesture filter such that it will not
+ * respond to input until new pointers are detected.
+ *
* @param dragObserver The callback interface to report all events related to dragging.
* @param canStartDragging If set, Before dragging is started ([DragObserver.onStart] is called),
* canStartDragging is called to check to see if it is allowed to start.
+ * @param orientation Limits the directions under which dragging can occur to those that are
+ * within the provided orientation, locks pointers that are used to drag in
+ * the given orientation to that orientation, and ignores pointers that are
+ * locked to other orientations. If no orientation is provided, does none of
+ * the above.
*/
-// TODO(b/129784010): Consider also allowing onStart, onDrag, and onStop to be set individually (instead of all being
-// set via DragObserver).
+// TODO(b/129784010): Consider also allowing onStart, onDrag, and onStop to be set individually
+// (instead of all being set via DragObserver).
fun Modifier.rawDragGestureFilter(
dragObserver: DragObserver,
- canStartDragging: (() -> Boolean)? = null
+ canStartDragging: (() -> Boolean)? = null,
+ orientation: Orientation? = null
): Modifier = composed {
val filter = remember { RawDragGestureFilter() }
filter.dragObserver = dragObserver
filter.canStartDragging = canStartDragging
+ filter.orientation = orientation
PointerInputModifierImpl(filter)
}
internal class RawDragGestureFilter : PointerInputFilter() {
private val velocityTrackers: MutableMap<PointerId, VelocityTracker> = mutableMapOf()
private val downPositions: MutableMap<PointerId, Offset> = mutableMapOf()
+
+ internal lateinit var dragObserver: DragObserver
+ internal var canStartDragging: (() -> Boolean)? = null
+ internal var orientation: Orientation? = null
+
private var started = false
- var canStartDragging: (() -> Boolean)? = null
- lateinit var dragObserver: DragObserver
+ internal lateinit var scrollOrientationLocker: ScrollOrientationLocker
+
+ override fun onInit(customEventDispatcher: CustomEventDispatcher) {
+ scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+ }
override fun onPointerInput(
changes: List<PointerInputChange>,
@@ -145,162 +179,202 @@
bounds: IntSize
): List<PointerInputChange> {
- var changesToReturn = changes
+ scrollOrientationLocker.onPointerInputSetup(changes, pass)
- if (pass == PointerEventPass.InitialDown) {
+ var changesToReturn = changes
- if (started) {
- // If we are have started we want to prevent any descendants from reacting to
- // any down change.
- changesToReturn = changesToReturn.map {
- if (it.changedToDown()) {
- it.consumeDownChange()
- } else {
- it
- }
+ if (pass == PointerEventPass.InitialDown) {
+
+ if (started) {
+ // If we are have started we want to prevent any descendants from reacting to
+ // any down change.
+ changesToReturn = changesToReturn.map {
+ if (it.changedToDown()) {
+ it.consumeDownChange()
+ } else {
+ it
+ }
+ }
+ }
+ }
+
+ if (pass == PointerEventPass.PostUp) {
+
+ val applicableChanges =
+ with(orientation) {
+ if (this != null) {
+ scrollOrientationLocker.getPointersFor(changes, this)
+ } else {
+ changes
+ }
+ }
+
+ // Handle up changes, which includes removing individual pointer VelocityTrackers
+ // and potentially calling onStop().
+ if (changesToReturn.fastAny { it.changedToUpIgnoreConsumed() }) {
+
+ var velocityTracker: VelocityTracker? = null
+
+ changesToReturn.fastForEach {
+ // This pointer is up (consumed or not), so we should stop tracking
+ // information about it. If the pointer is not locked out of our
+ // orientation, get the velocity tracker because this might be a fling.
+ if (it.changedToUp() && applicableChanges.contains(it)) {
+ velocityTracker = velocityTrackers.remove(it.id)
+ } else if (it.changedToUpIgnoreConsumed()) {
+ velocityTrackers.remove(it.id)
+ }
+ // removing stored down position for the pointer.
+ if (it.changedToUp()) {
+ downPositions.remove(it.id)
+ }
+ }
+
+ if (changesToReturn.all { it.changedToUpIgnoreConsumed() }) {
+ // All of the pointers are up, so reset and call onStop. If we have a
+ // velocityTracker at this point, that means at least one of the up events
+ // was not consumed so we should send velocity for flinging.
+ if (started) {
+ val velocity: Offset? =
+ if (velocityTracker != null) {
+ changesToReturn = changesToReturn.map {
+ it.consumeDownChange()
+ }
+ velocityTracker!!.calculateVelocity().pixelsPerSecond
+ } else {
+ null
+ }
+ started = false
+ dragObserver.onStop(velocity ?: Offset.Zero)
+ reset()
}
}
}
- if (pass == PointerEventPass.PostUp) {
-
- // Handle up changes, which includes removing individual pointer VelocityTrackers
- // and potentially calling onStop().
- if (changesToReturn.fastAny { it.changedToUpIgnoreConsumed() }) {
-
- var velocityTracker: VelocityTracker? = null
-
- changesToReturn.fastForEach {
- // This pointer is up (consumed or not), so we should stop tracking
- // information about it. Get a reference for the velocity tracker in case
- // this is the last pointer and thus we are going to fling.
- if (it.changedToUp()) {
- velocityTracker = velocityTrackers.remove(it.id)
- } else if (it.changedToUpIgnoreConsumed()) {
- velocityTrackers.remove(it.id)
- }
- // removing stored down position for the pointer.
- if (it.changedToUp()) {
- downPositions.remove(it.id)
- }
- }
-
- if (changesToReturn.all { it.changedToUpIgnoreConsumed() }) {
- // All of the pointers are up, so reset and call onStop. If we have a
- // velocityTracker at this point, that means at least one of the up events
- // was not consumed so we should send velocity for flinging.
- if (started) {
- val velocity: Offset? =
- if (velocityTracker != null) {
- changesToReturn = changesToReturn.map {
- it.consumeDownChange()
- }
- velocityTracker!!.calculateVelocity().pixelsPerSecond
- } else {
- null
- }
- started = false
- dragObserver.onStop(velocity ?: Offset.Zero)
- }
+ // For each new pointer that has been added, start tracking information about it.
+ if (changesToReturn.fastAny { it.changedToDownIgnoreConsumed() }) {
+ changesToReturn.fastForEach {
+ // If a pointer has changed to down, we should start tracking information
+ // about it.
+ if (it.changedToDownIgnoreConsumed()) {
+ velocityTrackers[it.id] = VelocityTracker()
+ .apply {
+ addPosition(
+ it.current.uptime!!,
+ it.current.position!!
+ )
+ }
+ downPositions[it.id] = it.current.position!!
}
}
+ }
+ }
- // For each new pointer that has been added, start tracking information about it.
- if (changesToReturn.fastAny { it.changedToDownIgnoreConsumed() }) {
- changesToReturn.fastForEach {
- // If a pointer has changed to down, we should start tracking information
- // about it.
- if (it.changedToDownIgnoreConsumed()) {
- velocityTrackers[it.id] = VelocityTracker()
- .apply {
- addPosition(
- it.current.uptime!!,
- it.current.position!!
- )
- }
- downPositions[it.id] = it.current.position!!
- }
+ // This if block is run for both PostUp and PostDown to allow for the detector to
+ // respond to modified changes after ancestors may have modified them. (This allows
+ // for things like dragging an ancestor scrolling container, while keeping a pointer on
+ // a descendant scrolling container, and the descendant scrolling container keeping the
+ // descendant still.)
+ if (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown) {
+
+ var (movedChanges, otherChanges) = changesToReturn.partition {
+ it.current.down && !it.changedToDownIgnoreConsumed()
+ }
+
+ movedChanges.fastForEach {
+ // TODO(shepshapard): handle the case that the pointerTrackingData is null,
+ // either with an exception or a logged error, or something else.
+ val velocityTracker = velocityTrackers[it.id]
+
+ if (velocityTracker != null) {
+
+ // Add information to the velocity tracker only during one pass.
+ // TODO(shepshapard): VelocityTracker needs to be updated to not accept
+ // position information, but rather vector information about movement.
+ if (pass == PointerEventPass.PostUp) {
+ velocityTracker.addPosition(
+ it.current.uptime!!,
+ it.current.position!!
+ )
}
}
}
- // This if block is run for both PostUp and PostDown to allow for the detector to
- // respond to modified changes after ancestors may have modified them. (This allows
- // for things like dragging an ancestor scrolling container, while keeping a pointer on
- // a descendant scrolling container, and the descendant scrolling container keeping the
- // descendant still.)
- if (pass == PointerEventPass.PostUp || pass == PointerEventPass.PostDown) {
+ // Check to see if we are already started so we don't have to call canStartDragging again.
+ val canStart = !started && canStartDragging?.invoke() ?: true
- var (movedChanges, otherChanges) = changesToReturn.partition {
- it.current.down && !it.changedToDownIgnoreConsumed()
- }
+ // At this point, check to see if we have started, and if we have, we may
+ // be calling onDrag and updating change information on the PointerInputChanges.
+ if (started || canStart) {
+
+ var totalDx = 0f
+ var totalDy = 0f
+
+ val verticalPointers =
+ scrollOrientationLocker.getPointersFor(
+ movedChanges,
+ Orientation.Vertical
+ )
+ val horizontalPointers =
+ scrollOrientationLocker.getPointersFor(
+ movedChanges,
+ Orientation.Horizontal
+ )
movedChanges.fastForEach {
- // TODO(shepshapard): handle the case that the pointerTrackingData is null,
- // either with an exception or a logged error, or something else.
- val velocityTracker = velocityTrackers[it.id]
-
- if (velocityTracker != null) {
-
- // Add information to the velocity tracker only during one pass.
- // TODO(shepshapard): VelocityTracker needs to be updated to not accept
- // position information, but rather vector information about movement.
- if (pass == PointerEventPass.PostUp) {
- velocityTracker.addPosition(
- it.current.uptime!!,
- it.current.position!!
- )
- }
- }
- }
-
- // Check to see if we are already started so we don't have to call canStartDragging again.
- val canStart = !started && canStartDragging?.invoke() ?: true
-
- // At this point, check to see if we have started, and if we have, we may
- // be calling onDrag and updating change information on the PointerInputChanges.
- if (started || canStart) {
-
- var totalDx = 0f
- var totalDy = 0f
-
- movedChanges.fastForEach {
+ if (horizontalPointers.contains(it) && orientation !=
+ Orientation.Vertical
+ ) {
totalDx += it.positionChange().x
+ }
+ if (verticalPointers.contains(it) && orientation !=
+ Orientation.Horizontal
+ ) {
totalDy += it.positionChange().y
}
-
- if (totalDx != 0f || totalDy != 0f) {
-
- // At this point, if we have not started, check to see if we should start
- // and if we should, update our state and call onStart().
- if (!started && canStart) {
- started = true
- dragObserver.onStart(downPositions.values.averagePosition())
- downPositions.clear()
- }
-
- if (started) {
-
- val consumed = dragObserver.onDrag(
- Offset(
- totalDx / changesToReturn.size,
- totalDy / changesToReturn.size
- )
- )
-
- movedChanges = movedChanges.map {
- it.consumePositionChange(consumed.x, consumed.y)
- }
- }
- }
}
- changesToReturn = movedChanges + otherChanges
+ if (totalDx != 0f || totalDy != 0f) {
+
+ // At this point, if we have not started, check to see if we should start
+ // and if we should, update our state and call onStart().
+ if (!started) {
+ started = true
+ dragObserver.onStart(downPositions.values.averagePosition())
+ downPositions.clear()
+ }
+
+ // Only need to do this during the first pass that we care about (PostUp).
+ if (pass == PointerEventPass.PostUp) {
+ orientation?.let {
+ scrollOrientationLocker.attemptToLockPointers(
+ movedChanges,
+ it
+ )
+ }
+ }
+
+ val consumed = dragObserver.onDrag(
+ Offset(
+ totalDx / changesToReturn.size,
+ totalDy / changesToReturn.size
+ )
+ )
+
+ movedChanges = movedChanges.map {
+ it.consumePositionChange(consumed.x, consumed.y)
+ }
+ }
}
- return changesToReturn
+ changesToReturn = movedChanges + otherChanges
}
+ scrollOrientationLocker.onPointerInputTearDown(changes, pass)
+
+ return changesToReturn
+ }
+
override fun onCancel() {
downPositions.clear()
velocityTrackers.clear()
@@ -308,13 +382,24 @@
started = false
dragObserver.onCancel()
}
+ scrollOrientationLocker.onCancel()
+ reset()
+ }
+
+ override fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
+ scrollOrientationLocker.onCustomEvent(customEvent, pass)
+ }
+
+ private fun reset() {
+ downPositions.clear()
+ velocityTrackers.clear()
}
}
private fun Iterable<Offset>.averagePosition(): Offset {
var x = 0f
var y = 0f
- forEach {
+ this.forEach {
x += it.x
y += it.y
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ScrollGestureFilter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ScrollGestureFilter.kt
new file mode 100644
index 0000000..7a7b055
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/ScrollGestureFilter.kt
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.gesture
+
+import androidx.compose.remember
+import androidx.ui.core.Direction
+import androidx.ui.core.Modifier
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.composed
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
+import androidx.ui.geometry.Offset
+
+/**
+ * Defines the callbacks associated with scrolling.
+ */
+interface ScrollCallback {
+
+ /**
+ * Override to be notified when a scroll has started.
+ *
+ * This will be called as soon as the average distance of all pointers surpasses the touch slop
+ * in the relevant orientation.
+ *
+ * Only called if the last called if the most recent call among [onStart], [onStop], and
+ * [onCancel] was [onStop] or [onCancel].
+ *
+ * @param downPosition The pointer input position of the down event.
+ */
+ fun onStart(downPosition: Offset) {}
+
+ /**
+ * Override to be notified when a distance has been scrolled.
+ *
+ * When overridden, return the amount of the [scrollDistance] that has been consumed.
+ *
+ * Called immediately after [onStart] and for every subsequent pointer movement, as long as the
+ * movement was enough to constitute a scroll (the average movement on in the relevant
+ * orientation is not equal to 0).
+ *
+ * Note: This may be called multiple times in a single pass and the values should be accumulated
+ * for each call.
+ *
+ * @param scrollDistance The distance that has been scrolled. Reflects the average scroll
+ * distance of all pointers.
+ */
+ fun onScroll(scrollDistance: Float) = 0f
+
+ /**
+ * Override to be notified when a scroll has stopped.
+ *
+ * This is called once all pointers have released the associated PointerInputFilter.
+ *
+ * Only called if the last called if the most recent call among [onStart], [onStop], and
+ * [onCancel] was [onStart].
+ *
+ * @param velocity The velocity of the scroll in the relevant orientation at the point in time
+ * when all pointers have released the relevant PointerInputFilter. In pixels per second.
+ */
+ fun onStop(velocity: Float) {}
+
+ /**
+ * Override to be notified when the scroll has been cancelled.
+ *
+ * This is called in response to a cancellation event such as the associated
+ * PointerInputFilter having been removed from the hierarchy.
+ *
+ * Only called if the last called if the most recent call among [onStart], [onStop], and
+ * [onCancel] was [onStart].
+ */
+ fun onCancel() {}
+}
+
+/**
+ * Like [Modifier.dragGestureFilter], this gesture filter will detect dragging, but will only do
+ * so along the given [orientation].
+ *
+ * This gesture filter also disambiguates amongst other scrollGestureFilters such that for all
+ * pointers that this gesture filter uses to scroll in the given [orientation], other
+ * scrollGestureFilters (or other clients of [ScrollOrientationLocker]) will not use those same
+ * pointers to drag in the other [orientation]. Likewise, this scrollGestureFilter will not use
+ * pointers to drag if they are already being used to drag in a different orientation.
+ *
+ * Note: [canDrag] will only be queried in directions that exist within the given [orientation].
+ *
+ * Note: Changing the value of [orientation] will reset the gesture filter such that it will not
+ * respond to input until new pointers are detected.
+ *
+ * @param scrollCallback: The set of callbacks for scrolling.
+ * @param orientation: The orientation this gesture filter uses.
+ * @param canDrag Set to limit the types of directions under which touch slop can be exceeded.
+ * Return true if you want a drag to be started due to the touch slop being surpassed in the
+ * given [Direction]. If [canDrag] is not provided, touch slop will be able to be exceeded in all
+ * directions that are in the provided [orientation].
+ * @param startDragImmediately Set to true to have dragging begin immediately when a pointer is
+ * "down", preventing children from responding to the "down" change. Generally, this parameter
+ * should be set to true when the child of the GestureDetector is animating, such that when a finger
+ * touches it, dragging is immediately started so the animation stops and dragging can occur.
+ */
+// TODO(shepshapard): Consider breaking up ScrollCallback such that the onScroll lambda can be
+// the final parameter.
+fun Modifier.scrollGestureFilter(
+ scrollCallback: ScrollCallback,
+ orientation: Orientation,
+ canDrag: ((Direction) -> Boolean)? = null,
+ startDragImmediately: Boolean = false
+): Modifier = composed {
+ val coordinator = remember { ScrollGestureFilterCoordinator() }
+ coordinator.scrollCallback = scrollCallback
+ coordinator.orientation = orientation
+
+ // TODO(b/146427920): There is a gap here where RawPressStartGestureDetector can cause a call to
+ // DragObserver.onStart but if the pointer doesn't move and releases, (or if cancel is called)
+ // The appropriate callbacks to DragObserver will not be called.
+ rawDragGestureFilter(
+ coordinator.rawDragObserver,
+ coordinator::enabledOrStarted,
+ orientation
+ )
+ .dragSlopExceededGestureFilter(coordinator::enableDrag, canDrag, orientation)
+ .rawPressStartGestureFilter(
+ coordinator::startDrag,
+ startDragImmediately,
+ PointerEventPass.InitialDown
+ )
+}
+
+/**
+ * Coordinates the logic of rawDragGestureFilter, dragSlopExceededGestureFilter, and
+ * rawPressStartGestureFilter.
+ *
+ * Also maps the output of rawDragGestureFilter to the output of scrollGestureFilter.
+ */
+private class ScrollGestureFilterCoordinator {
+ private var started = false
+ private var enabled = false
+
+ lateinit var scrollCallback: ScrollCallback
+ lateinit var orientation: Orientation
+
+ val enabledOrStarted
+ get() = started || enabled
+
+ fun enableDrag() {
+ enabled = true
+ }
+
+ fun startDrag(downPosition: Offset) {
+ started = true
+ scrollCallback.onStart(downPosition)
+ }
+
+ val rawDragObserver: DragObserver =
+ object : DragObserver {
+ override fun onStart(downPosition: Offset) {
+ if (!started) {
+ scrollCallback.onStart(downPosition)
+ }
+ }
+
+ override fun onDrag(dragDistance: Offset): Offset {
+ return when (orientation) {
+ Orientation.Horizontal -> Offset(scrollCallback.onScroll(dragDistance.x), 0f)
+ Orientation.Vertical -> Offset(0f, scrollCallback.onScroll(dragDistance.y))
+ }
+ }
+
+ override fun onStop(velocity: Offset) {
+ started = false
+ enabled = false
+ return when (orientation) {
+ Orientation.Horizontal -> scrollCallback.onStop(velocity.x)
+ Orientation.Vertical -> scrollCallback.onStop(velocity.y)
+ }
+ }
+
+ override fun onCancel() {
+ started = false
+ enabled = false
+ scrollCallback.onCancel()
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLocker.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLocker.kt
new file mode 100644
index 0000000..9f2a102
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLocker.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.gesture.scrollorientationlocking
+
+import androidx.annotation.VisibleForTesting
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerId
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.changedToDownIgnoreConsumed
+import androidx.ui.core.changedToUpIgnoreConsumed
+import androidx.ui.core.gesture.ExperimentalPointerInput
+import androidx.ui.core.pointerinput.PointerInputFilter
+import androidx.ui.util.fastForEach
+
+// TODO(shepshapard): This should be in a more generic place.
+enum class Orientation {
+ Vertical, Horizontal
+}
+
+/**
+ * Manages scroll orientation locking amongst all participating gesture filters.
+ *
+ * Does so by allowing gesture filters to do the following:
+ *
+ * 1. Request that pointers be locked to particular [Orientation]s
+ * 2. Query which pointers from a given set are allowed to be considered for a given orientation.
+ *
+ * A specific contract must also be followed in order to setup and tear down scroll orientation
+ * locking. Please see [onPointerInputSetup], [onPointerInputTearDown], [onCustomEvent], and
+ * [onCancel] to use
+ * this correctly.
+ */
+@ExperimentalPointerInput
+class ScrollOrientationLocker(private val customEventDispatcher: CustomEventDispatcher) {
+
+ private var locker: InternalScrollOrientationLocker? = null
+ private var lockerOwner = false
+
+ /**
+ * Handles the initialization of scroll orientation locking management, including internally
+ * managed distribution of shared state.
+ *
+ * For proper initialization to work, [onCustomEvent] must also be called in
+ * [PointerInputFilter.onCustomEvent].
+ *
+ * This method should simply be called toward the top of [PointerInputFilter.onPointerInput]
+ * for all [PointerEventPass]es, before [attemptToLockPointers] or [getPointersFor] are called.
+ *
+ * @see onPointerInputTearDown
+ * @see onCancel
+ * @see onCustomEvent
+ */
+ fun onPointerInputSetup(changes: List<PointerInputChange>, pass: PointerEventPass) {
+ if (pass != PointerEventPass.InitialDown) {
+ return
+ }
+
+ if (locker == null && changes.all { it.changedToDownIgnoreConsumed() }) {
+ lockerOwner = true
+ locker = InternalScrollOrientationLocker().also {
+ customEventDispatcher.dispatchCustomEvent(
+ ShareScrollOrientationLockerEvent(it)
+ )
+ }
+ } else if (lockerOwner && changes.any { it.changedToDownIgnoreConsumed() }) {
+ // TODO(shepshapard): This is always doing some extra work given that some of the
+ // child gesture filters may already have received the InternalScrollOrientationLocker.
+ // It is functionality correct, but could be optimized (though it would likely
+ // not provide that much of a performance boost in the real world.
+ customEventDispatcher.dispatchCustomEvent(
+ ShareScrollOrientationLockerEvent(locker!!)
+ )
+ }
+ }
+
+ /**
+ * Handles the tear down of internal state.
+ *
+ * This method must be called toward the bottom of [PointerInputFilter.onPointerInput]
+ * for all [PointerEventPass]es, and [attemptToLockPointers] or [getPointersFor] should not
+ * be called afterwards.
+ *
+ * @see onPointerInputSetup
+ * @see onCancel
+ * @see onCustomEvent
+ */
+ fun onPointerInputTearDown(changes: List<PointerInputChange>, pass: PointerEventPass) {
+ if (pass == PointerEventPass.PostDown && changes.all { it.changedToUpIgnoreConsumed() }) {
+ reset()
+ }
+ }
+
+ /**
+ * Handles the tear down of internal state due to a call to [PointerInputFilter.onCancel].
+ *
+ * Must be called in [PointerInputFilter.onCancel].
+ *
+ * @see onPointerInputSetup
+ * @see onPointerInputTearDown
+ * @see onCustomEvent
+ */
+ fun onCancel() {
+ reset()
+ }
+
+ /**
+ * Handles the other half of [onPointerInputSetup] and must be called in all calls to
+ * [PointerInputFilter.onCustomEvent].
+ *
+ * @see onPointerInputSetup
+ * @see onPointerInputTearDown
+ * @see onCancel
+ * @throws [IllegalStateException] if this [ScrollOrientationLocker] receives a
+ * [ShareScrollOrientationLockerEvent] via this method after having already dispatched a
+ * [ShareScrollOrientationLockerEvent] itself.
+ */
+ fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
+
+ if (pass == PointerEventPass.InitialDown &&
+ customEvent is ShareScrollOrientationLockerEvent) {
+ if (lockerOwner) {
+ throw IllegalStateException("This instance of ScrollOrientationLocker should " +
+ "never receive a ShareScrollOrientationLockerEvent because it already " +
+ "dispatched one, and thus should be the only one in it's subtree to " +
+ "dispatch one.")
+ }
+ locker = customEvent.scrollOrientationLocker
+ }
+ }
+
+ /**
+ * Locks the [PointerId]s associated with the [changes] to [orientation].
+ *
+ * This effects which [changes] are returned by [getPointersFor].
+ *
+ * Pointers that are already locked to a given orientation cannot be later locked to a different
+ * orientation.
+ *
+ * @throws [IllegalStateException] if this method is called when this
+ * [ScrollOrientationLocker] has not yet been initialized. This is likely happening because
+ * [onPointerInputSetup] is not being called with every [PointerEventPass] before this method
+ * is being called.
+ */
+ fun attemptToLockPointers(changes: List<PointerInputChange>, orientation: Orientation) {
+ if (locker == null) {
+ throw IllegalStateException("Internal state has not been set. This method should not" +
+ " be called in any place but after calls to onPointerInputSetup and before " +
+ "calls to onPointerInputTearDown or onCancel. Also, onCustomEvent must be " +
+ "called appropriately. See docs for details.")
+ }
+ locker!!.attemptToLockPointers(changes, orientation)
+ }
+
+ /**
+ * Filters the [changes] for those that are allowed to be acted upon for the [orientation].
+ *
+ * A change can be acted on if it was not already locked in the other orientation.
+ *
+ * For example, if pointer 1 was previously locked to Horizontal via [attemptToLockPointers]
+ * then calling this method with pointers 1 and 2 and the following orientation will result
+ * in the following pointers being returned:
+ *
+ * - Orientation.Horizontal -> (1, 2)
+ * - Orientation.Vertical -> (2)
+ *
+ * @throws [IllegalStateException] if this method is called when this
+ * [ScrollOrientationLocker] has not yet been initialized. This is likely happening because
+ * [onPointerInputSetup] is not being called with every [PointerEventPass] before this method
+ * is being called.
+ */
+ fun getPointersFor(
+ changes: List<PointerInputChange>,
+ orientation: Orientation
+ ): List<PointerInputChange> {
+ if (locker == null) {
+ throw IllegalStateException("Internal state has not been set. This method should not" +
+ " be called in any place but after calls to onPointerInputSetup and before " +
+ "calls to onPointerInputTearDown or onCancel. Also, onCustomEvent must be " +
+ "called appropriately. See docs for details.")
+ }
+ return locker!!.getPointersFor(changes, orientation)
+ }
+
+ private fun reset() {
+ locker = null
+ lockerOwner = false
+ }
+}
+
+@VisibleForTesting
+internal class InternalScrollOrientationLocker {
+ private val pointerLocks: MutableMap<PointerId, Orientation> = mutableMapOf()
+
+ fun attemptToLockPointers(pointerIds: List<PointerInputChange>, orientation: Orientation) {
+ pointerIds.fastForEach {
+ if (pointerLocks[it.id] == null) {
+ pointerLocks[it.id] = orientation
+ }
+ }
+ }
+
+ fun getPointersFor(
+ pointerIds: List<PointerInputChange>,
+ orientation: Orientation
+ ): List<PointerInputChange> {
+ return pointerIds
+ .filter { pointerLocks[it.id] == null || pointerLocks[it.id] == orientation }
+ }
+}
+
+@VisibleForTesting
+internal class ShareScrollOrientationLockerEvent(
+ val scrollOrientationLocker: InternalScrollOrientationLocker
+) : CustomEvent
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt
index 785acc9..ec1898b 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionContainer.kt
@@ -20,27 +20,15 @@
import androidx.compose.Providers
import androidx.compose.remember
import androidx.compose.state
-import androidx.ui.core.Alignment
import androidx.ui.core.ClipboardManagerAmbient
-import androidx.ui.core.Constraints
import androidx.ui.core.HapticFeedBackAmbient
-import androidx.ui.core.Layout
import androidx.ui.core.Modifier
-import androidx.ui.core.Placeable
-import androidx.ui.core.Popup
import androidx.ui.core.TextToolbarAmbient
-import androidx.ui.core.enforce
import androidx.ui.core.gesture.dragGestureFilter
import androidx.ui.core.gesture.longPressDragGestureFilter
import androidx.ui.core.gesture.tapGestureFilter
-import androidx.ui.core.hasFixedHeight
-import androidx.ui.core.hasFixedWidth
import androidx.ui.core.onPositioned
-import androidx.ui.unit.Dp
-import androidx.ui.unit.IntOffset
-import androidx.ui.unit.IntSize
-import kotlin.math.max
-import kotlin.math.roundToInt
+import androidx.ui.text.InternalTextApi
/**
* Default SelectionContainer to be used in order to make composables selectable by default.
@@ -61,6 +49,7 @@
* The selection composable wraps composables and let them to be selectable. It paints the selection
* area with start and end handles.
*/
+@OptIn(InternalTextApi::class)
@Composable
fun SelectionContainer(
/** Current Selection status.*/
@@ -92,131 +81,33 @@
Providers(SelectionRegistrarAmbient provides registrarImpl) {
// Get the layout coordinates of the selection container. This is for hit test of
// cross-composable selection.
- Wrap(modifier) {
+ SelectionLayout(modifier) {
children()
- for (isStartHandle in listOf(true, false)) {
- Handle(manager, isStartHandle) {
- SelectionHandle(
- Modifier.dragGestureFilter(manager.handleDragObserver(isStartHandle)),
- manager.selection,
- isStartHandle)
+ manager.selection?.let {
+ for (isStartHandle in listOf(true, false)) {
+ SelectionHandleLayout(
+ startHandlePosition = manager.startHandlePosition,
+ endHandlePosition = manager.endHandlePosition,
+ isStartHandle = isStartHandle,
+ directions = Pair(it.start.direction, it.end.direction),
+ handlesCrossed = it.handlesCrossed
+ ) {
+ SelectionHandle(
+ modifier =
+ Modifier.dragGestureFilter(manager.handleDragObserver(isStartHandle)),
+ isStartHandle = isStartHandle,
+ directions = Pair(it.start.direction, it.end.direction),
+ handlesCrossed = it.handlesCrossed
+ )
+ }
}
+ SelectionFloatingToolBar(manager = manager)
}
- SelectionFloatingToolBar(manager = manager, selection = selection)
}
}
}
@Composable
-private fun SelectionFloatingToolBar(manager: SelectionManager, selection: Selection?) {
- if (selection == null) return
+private fun SelectionFloatingToolBar(manager: SelectionManager) {
manager.showSelectionToolbar()
}
-
-@Composable
-private fun Handle(
- manager: SelectionManager,
- isStartHandle: Boolean,
- handle: @Composable () -> Unit
-) {
- val offset = if (isStartHandle) manager.startHandlePosition else manager.endHandlePosition
- val selection = manager.selection
- if (offset == null || selection == null) {
- return
- }
-
- Wrap {
- val left = isLeft(isStartHandle, selection)
- val alignment = if (left) Alignment.TopEnd else Alignment.TopStart
-
- Popup(
- alignment = alignment,
- offset = IntOffset(offset.x.roundToInt(), offset.y.roundToInt()),
- children = handle
- )
- }
-}
-
-/**
- * Selection is transparent in terms of measurement and layout and passes the same constraints to
- * the children.
- */
-@Composable
-private fun Wrap(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
- Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
- val placeables = measurables.map { measurable ->
- measurable.measure(constraints)
- }
-
- val width = placeables.fold(0) { maxWidth, placeable ->
- max(maxWidth, (placeable.width))
- }
-
- val height = placeables.fold(0) { minWidth, placeable ->
- max(minWidth, (placeable.height))
- }
-
- layout(width, height) {
- placeables.forEach { placeable ->
- placeable.placeAbsolute(0, 0)
- }
- }
- }
-}
-
-/**
- * A Container Box implementation used for selection children and handle layout
- */
-@Composable
-internal fun SimpleContainer(
- modifier: Modifier = Modifier,
- width: Dp? = null,
- height: Dp? = null,
- children: @Composable () -> Unit
-) {
- Layout(children, modifier) { measurables, incomingConstraints, _ ->
- val containerConstraints = Constraints()
- .copy(
- width?.toIntPx() ?: 0,
- width?.toIntPx() ?: Constraints.Infinity,
- height?.toIntPx() ?: 0,
- height?.toIntPx() ?: Constraints.Infinity
- )
- .enforce(incomingConstraints)
- val childConstraints = containerConstraints.copy(minWidth = 0, minHeight = 0)
- var placeable: Placeable? = null
- val containerWidth = if (
- containerConstraints.hasFixedWidth
- ) {
- containerConstraints.maxWidth
- } else {
- placeable = measurables.firstOrNull()?.measure(childConstraints)
- max((placeable?.width ?: 0), containerConstraints.minWidth)
- }
- val containerHeight = if (
- containerConstraints.hasFixedHeight
- ) {
- containerConstraints.maxHeight
- } else {
- if (placeable == null) {
- placeable = measurables.firstOrNull()?.measure(childConstraints)
- }
- max((placeable?.height ?: 0), containerConstraints.minHeight)
- }
- layout(containerWidth, containerHeight) {
- val p = placeable ?: measurables.firstOrNull()?.measure(childConstraints)
- p?.let {
- val position = Alignment.Center.align(
- IntSize(
- containerWidth - it.width,
- containerHeight - it.height
- )
- )
- it.place(
- position.x,
- position.y
- )
- }
- }
- }
-}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt
index 3cd7593..1bc3d9a 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionHandles.kt
@@ -26,6 +26,7 @@
import androidx.ui.graphics.Color
import androidx.ui.graphics.Path
import androidx.ui.graphics.drawscope.DrawScope
+import androidx.ui.text.InternalTextApi
import androidx.ui.text.style.TextDirection
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
@@ -115,19 +116,20 @@
}
}
+/**
+ * @suppress
+ */
+@InternalTextApi
@Composable
-internal fun SelectionHandle(
+fun SelectionHandle(
modifier: Modifier,
- selection: Selection?,
- isStartHandle: Boolean
+ isStartHandle: Boolean,
+ directions: Pair<TextDirection, TextDirection>,
+ handlesCrossed: Boolean
) {
- if (selection == null) {
- return
- }
-
SelectionHandleLayout(
modifier,
- isLeft(isStartHandle, selection))
+ isLeft(isStartHandle, directions, handlesCrossed))
}
/**
@@ -135,12 +137,13 @@
*/
internal fun isLeft(
isStartHandle: Boolean,
- selection: Selection
+ directions: Pair<TextDirection, TextDirection>,
+ handlesCrossed: Boolean
): Boolean {
if (isStartHandle) {
- return isHandleLtrDirection(selection.start.direction, selection.handlesCrossed)
+ return isHandleLtrDirection(directions.first, handlesCrossed)
} else {
- return !isHandleLtrDirection(selection.end.direction, selection.handlesCrossed)
+ return !isHandleLtrDirection(directions.second, handlesCrossed)
}
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionLayout.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionLayout.kt
new file mode 100644
index 0000000..69b9aad
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/selection/SelectionLayout.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.core.selection
+
+import androidx.compose.Composable
+import androidx.ui.core.Alignment
+import androidx.ui.core.Constraints
+import androidx.ui.core.Layout
+import androidx.ui.core.Modifier
+import androidx.ui.core.Placeable
+import androidx.ui.core.Popup
+import androidx.ui.core.enforce
+import androidx.ui.core.hasFixedHeight
+import androidx.ui.core.hasFixedWidth
+import androidx.ui.geometry.Offset
+import androidx.ui.text.InternalTextApi
+import androidx.ui.text.style.TextDirection
+import androidx.ui.unit.Dp
+import androidx.ui.unit.IntOffset
+import androidx.ui.unit.IntSize
+import kotlin.math.max
+import kotlin.math.roundToInt
+
+/**
+ * @suppress
+ */
+@InternalTextApi
+@Composable
+fun SelectionHandleLayout(
+ startHandlePosition: Offset?,
+ endHandlePosition: Offset?,
+ isStartHandle: Boolean,
+ directions: Pair<TextDirection, TextDirection>,
+ handlesCrossed: Boolean,
+ handle: @Composable () -> Unit
+) {
+ val offset = (if (isStartHandle) startHandlePosition else endHandlePosition) ?: return
+
+ SelectionLayout {
+ val left = isLeft(
+ isStartHandle = isStartHandle,
+ directions = directions,
+ handlesCrossed = handlesCrossed
+ )
+ val alignment = if (left) Alignment.TopEnd else Alignment.TopStart
+
+ Popup(
+ alignment = alignment,
+ offset = IntOffset(offset.x.roundToInt(), offset.y.roundToInt()),
+ children = handle
+ )
+ }
+}
+
+/**
+ * Selection is transparent in terms of measurement and layout and passes the same constraints to
+ * the children.
+ * @suppress
+ */
+@InternalTextApi
+@Composable
+fun SelectionLayout(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
+ Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
+ val placeables = measurables.map { measurable ->
+ measurable.measure(constraints)
+ }
+
+ val width = placeables.fold(0) { maxWidth, placeable ->
+ max(maxWidth, (placeable.width))
+ }
+
+ val height = placeables.fold(0) { minWidth, placeable ->
+ max(minWidth, (placeable.height))
+ }
+
+ layout(width, height) {
+ placeables.forEach { placeable ->
+ placeable.placeAbsolute(0, 0)
+ }
+ }
+ }
+}
+
+/**
+ * A Container Box implementation used for selection children and handle layout
+ */
+@Composable
+internal fun SimpleContainer(
+ modifier: Modifier = Modifier,
+ width: Dp? = null,
+ height: Dp? = null,
+ children: @Composable () -> Unit
+) {
+ Layout(children, modifier) { measurables, incomingConstraints, _ ->
+ val containerConstraints = Constraints()
+ .copy(
+ width?.toIntPx() ?: 0,
+ width?.toIntPx() ?: Constraints.Infinity,
+ height?.toIntPx() ?: 0,
+ height?.toIntPx() ?: Constraints.Infinity
+ )
+ .enforce(incomingConstraints)
+ val childConstraints = containerConstraints.copy(minWidth = 0, minHeight = 0)
+ var placeable: Placeable? = null
+ val containerWidth = if (
+ containerConstraints.hasFixedWidth
+ ) {
+ containerConstraints.maxWidth
+ } else {
+ placeable = measurables.firstOrNull()?.measure(childConstraints)
+ max((placeable?.width ?: 0), containerConstraints.minWidth)
+ }
+ val containerHeight = if (
+ containerConstraints.hasFixedHeight
+ ) {
+ containerConstraints.maxHeight
+ } else {
+ if (placeable == null) {
+ placeable = measurables.firstOrNull()?.measure(childConstraints)
+ }
+ max((placeable?.height ?: 0), containerConstraints.minHeight)
+ }
+ layout(containerWidth, containerHeight) {
+ val p = placeable ?: measurables.firstOrNull()?.measure(childConstraints)
+ p?.let {
+ val position = Alignment.Center.align(
+ IntSize(
+ containerWidth - it.width,
+ containerHeight - it.height
+ )
+ )
+ it.place(
+ position.x,
+ position.y
+ )
+ }
+ }
+ }
+}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
index cc8d000..00e458f 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
@@ -32,13 +32,6 @@
val id: Int
/**
- * If true, then the semantics modifier applies to the first layout node below it in the tree,
- * not the composable the modifier is applied to. This is for use by legacy non-modifier-style
- * semantics and is planned to be removed (with the behavior 'false' made universal).
- */
- val applyToChildLayoutNode: Boolean
-
- /**
* The SemanticsConfiguration holds substantive data, especially a list of key/value pairs
* such as (label -> "buttonName").
*/
@@ -47,7 +40,6 @@
internal class SemanticsModifierCore(
override val id: Int,
- override val applyToChildLayoutNode: Boolean,
mergeAllDescendants: Boolean,
properties: (SemanticsPropertyReceiver.() -> Unit)?
) : SemanticsModifier {
@@ -62,20 +54,15 @@
/**
* Add semantics key/value for use in testing, accessibility, and similar use cases.
*
- * @param applyToChildLayoutNode If true, then the semantics modifier applies to the first layout
- * node below it in the tree, not the composable the modifier is applied to. This is for use by
- * legacy non-modifier-style semantics and is planned to be removed (with the behavior 'false'
- * made universal).
* @param mergeAllDescendants Whether the semantic information provided by the owning component and
* all of its descendants should be treated as one logical entity.
* @param properties properties to add to the semantics. [SemanticsPropertyReceiver] will be
* provided in the scope to allow access for common properties and its values.
*/
fun Modifier.semantics(
- applyToChildLayoutNode: Boolean = false,
mergeAllDescendants: Boolean = false,
properties: (SemanticsPropertyReceiver.() -> Unit)? = null
): Modifier = composed {
val id = remember { SemanticsNode.generateNewId() }
- SemanticsModifierCore(id, applyToChildLayoutNode, mergeAllDescendants, properties)
+ SemanticsModifierCore(id, mergeAllDescendants, properties)
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
index bc8e948..09b6fbe 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
@@ -16,6 +16,7 @@
package androidx.ui.core.semantics
+import androidx.ui.core.AlignmentLine
import androidx.ui.core.LayoutNode
import androidx.ui.core.LayoutNodeWrapper
import androidx.ui.core.boundsInRoot
@@ -82,36 +83,31 @@
* Each semantic node has a unique identifier that is assigned when the node
* is created.
*/
- internal constructor(unmergedConfig: SemanticsConfiguration, componentNode: LayoutNode) :
- this(generateNewId(), unmergedConfig, componentNode)
+ internal constructor(unmergedConfig: SemanticsConfiguration, layoutNode: LayoutNode) :
+ this(generateNewId(), unmergedConfig, layoutNode)
// GEOMETRY
/** The size of the bounding box for this node */
val size: IntSize
get() {
- return layoutNode.coordinates.size
+ return componentNode.coordinates.size
}
/** The bounding box for this node relative to the root of this Compose hierarchy */
val boundsInRoot: PxBounds
get() {
- return layoutNode.coordinates.boundsInRoot
+ return componentNode.coordinates.boundsInRoot
}
val globalBounds: PxBounds
get() {
- return layoutNode.coordinates.globalBounds
+ return componentNode.coordinates.globalBounds
}
val globalPosition: Offset
get() {
- return layoutNode.coordinates.globalPosition
- }
-
- private val layoutNode: LayoutNode
- get() {
- return componentNode.requireLayoutNodeAppliedTo()
+ return componentNode.coordinates.globalPosition
}
/**
@@ -124,6 +120,14 @@
return buildMergedConfig()
}
+ /**
+ * Returns the position of an [alignment line][AlignmentLine], or [AlignmentLine.Unspecified]
+ * if the line is not provided.
+ */
+ fun getAlignmentLinePosition(line: AlignmentLine): Int {
+ return componentNode.coordinates[line]
+ }
+
private fun buildMergedConfig(
parentNode: SemanticsNode? = null,
mergedConfigFromParent: SemanticsConfiguration? = null,
@@ -174,12 +178,7 @@
private fun unmergedChildren(): List<SemanticsNode> {
val unmergedChildren: MutableList<SemanticsNode> = mutableListOf()
- var searchRoot: LayoutNode? = componentNode
- if (searchRoot?.outerSemantics?.semanticsModifier?.applyToChildLayoutNode == true) {
- searchRoot = componentNode.findLastConsecutiveSemanticsNode()
- }
- val semanticsChildren =
- searchRoot?.findOneLayerOfSemanticsWrappers() ?: emptyList()
+ val semanticsChildren = componentNode.findOneLayerOfSemanticsWrappers()
semanticsChildren.fastForEach { semanticsChild ->
unmergedChildren.add(semanticsChild.semanticsNode())
}
@@ -243,23 +242,7 @@
// TODO(b/145947383): this needs to be the *merged* parent
val parent: SemanticsNode?
get() {
- // This searches up the layout tree and takes into account
- // collapsing of adjacent SemanticsWrappers into a single
- // SemanticsNode.
- // Example: if L are normal layout node and S are semantics nodes,
- // and the ComponentNode tree is a simple list-like tree
- // "<ROOT>, S, S, L, S, S, S, L, L, S"
- // ^ ^ ^
- // a b c
- // then 'c'.parent == 'b', and 'b'.parent == 'a'
-
- // (This complexity is temporary -- semantics collapsing will be
- // replaced by modifier chains soon.)
-
- var node = componentNode
- .findClosestParentNode { it.outerSemantics != null }
- ?.findHighestConsecutiveAncestor {
- it.outerSemantics?.semanticsModifier?.applyToChildLayoutNode == true }
+ var node = componentNode.findClosestParentNode { it.outerSemantics != null }
return node?.outerSemantics?.semanticsNode()
}
@@ -292,21 +275,6 @@
}
/**
- * Returns the highest in a consecutive chain of this + this's parents all meeting the predicate.
-*/
-private fun LayoutNode.findHighestConsecutiveAncestor(
- selector: (LayoutNode) -> Boolean
-): LayoutNode? {
- var prev = this
- var currentParent = parent
- while (currentParent != null && selector(currentParent)) {
- prev = currentParent
- currentParent = currentParent.parent
- }
- return prev
-}
-
-/**
* Executes [selector] on every parent of this [SemanticsNode] and returns the closest
* [SemanticsNode] to return `true` from [selector] or null if [selector] returns false
* for all ancestors.
@@ -334,11 +302,11 @@
}
private fun LayoutNode.findOneLayerOfSemanticsWrappers(): List<SemanticsWrapper> {
- val childSemanticsComponentNodes = mutableListOf<SemanticsWrapper>()
+ val childSemanticsLayoutNodes = mutableListOf<SemanticsWrapper>()
children.fastForEach { child ->
- findOneLayerOfSemanticsWrappersRecursive(childSemanticsComponentNodes, child)
+ findOneLayerOfSemanticsWrappersRecursive(childSemanticsLayoutNodes, child)
}
- return childSemanticsComponentNodes
+ return childSemanticsLayoutNodes
}
private fun LayoutNode.findOneLayerOfSemanticsWrappersRecursive(
@@ -354,35 +322,3 @@
}
}
}
-
-private fun LayoutNode.findLastConsecutiveSemanticsNode(): LayoutNode? {
- children.fastForEach { child ->
- if (child.outerSemantics != null) {
- if (child.outerSemantics?.semanticsModifier?.applyToChildLayoutNode == false)
- return child
- return child.findLastConsecutiveSemanticsNode()
- } // else, keep looking through the other children
- }
-
- return this
-}
-
-private fun LayoutNode.findLayoutNodeAppliedTo(): LayoutNode? {
- if ((outerSemantics == null ||
- outerSemantics?.semanticsModifier?.applyToChildLayoutNode == false)) {
- return this
- }
- children.fastForEach { child ->
- val layoutChild = child.findLayoutNodeAppliedTo()
- if (layoutChild != null) {
- return layoutChild
- }
- }
-
- return null
-}
-
-private fun LayoutNode.requireLayoutNodeAppliedTo(): LayoutNode {
- return findLayoutNodeAppliedTo()
- ?: throw IllegalStateException("This component has no layout children")
-}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
index 083cfc4..2069190 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
@@ -18,7 +18,6 @@
import androidx.ui.core.DelegatingLayoutNodeWrapper
import androidx.ui.core.LayoutNodeWrapper
-import androidx.ui.util.fastForEach
internal class SemanticsWrapper(
wrapped: LayoutNodeWrapper,
@@ -32,49 +31,25 @@
fun collapsedSemanticsConfiguration(): SemanticsConfiguration {
var config = SemanticsConfiguration()
- collapseChainedSemanticsIntoTopConfig(config, this)
+ config.absorb(modifier.semanticsConfiguration, ignoreAlreadySet = true)
+
+ val innerConfig = wrapped.nearestSemantics?.collapsedSemanticsConfiguration()
+ if (innerConfig != null) {
+ config.absorb(innerConfig, ignoreAlreadySet = true)
+ }
return config
}
+ override fun detach() {
+ super.detach()
+ layoutNode.owner?.onSemanticsChange()
+ }
+
+ override fun onModifierChanged() {
+ layoutNode.owner?.onSemanticsChange()
+ }
+
override fun toString(): String {
return "${super.toString()} localConfig: ${modifier.semanticsConfiguration}"
}
-
- /**
- * "Collapses" together the [SemanticsConfiguration]s that will apply to the child [LayoutNode].
- *
- * This ignores semantic boundaries (because they only apply once the node
- * is built), and currently does not validate that a [LayoutNode] actually
- * exists as a child (though this is not contractual)
- */
- private fun collapseChainedSemanticsIntoTopConfig(
- parentConfig: SemanticsConfiguration,
- topNodeOfConfig: SemanticsWrapper
- ) {
- parentConfig.absorb(modifier.semanticsConfiguration, ignoreAlreadySet = true)
-
- if (semanticsModifier.applyToChildLayoutNode) {
- // Recursively collapse the chain, if we have an immediate child
- findOneImmediateChild()?.collapseChainedSemanticsIntoTopConfig(
- parentConfig, topNodeOfConfig)
- } else {
- // Collapse locally within the modifiers directly applying to the current layout node
- val innerConfig = wrapped.nearestSemantics?.collapsedSemanticsConfiguration()
- if (innerConfig != null) {
- parentConfig.absorb(innerConfig, ignoreAlreadySet = true)
- }
- }
- }
-
- // This searches the children down only one level of the tree and returns one child found.
- // Note that this assumes each LayoutNode only has one semantics modifier for now.
- private fun findOneImmediateChild(): SemanticsWrapper? {
- var immediateChild: SemanticsWrapper? = null
- layoutNode.children.fastForEach { child ->
- if (child.outerSemantics != null) {
- immediateChild = child.outerSemantics
- }
- }
- return immediateChild
- }
}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt
index 85db0b7..a42aac7 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorCompose.kt
@@ -16,25 +16,21 @@
@file:OptIn(ExperimentalComposeApi::class)
package androidx.ui.graphics.vector
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
+import androidx.compose.AbstractApplier
import androidx.compose.Composable
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
import androidx.compose.CompositionReference
import androidx.compose.Composition
import androidx.compose.ExperimentalComposeApi
-import androidx.compose.ComposeCompilerApi
import androidx.compose.Recomposer
-import androidx.compose.SlotTable
import androidx.compose.compositionFor
-import androidx.compose.currentComposer
+import androidx.compose.emit
+import androidx.compose.key
import androidx.ui.graphics.Brush
import androidx.ui.graphics.StrokeCap
import androidx.ui.graphics.StrokeJoin
@Composable
-fun VectorScope.Group(
+fun Group(
name: String = DefaultGroupName,
rotation: Float = DefaultRotation,
pivotX: Float = DefaultPivotX,
@@ -44,25 +40,29 @@
translationX: Float = DefaultTranslationX,
translationY: Float = DefaultTranslationY,
clipPathData: List<PathNode> = EmptyPath,
- children: @Composable VectorScope.() -> Unit
+ children: @Composable () -> Unit
) {
- GroupComponent(
- name = name,
- rotation = rotation,
- pivotX = pivotX,
- pivotY = pivotY,
- scaleX = scaleX,
- scaleY = scaleY,
- translationX = translationX,
- translationY = translationY,
- clipPathData = clipPathData
- ) {
- children()
+ key(name) {
+ emit<GroupComponent, VectorApplier>(
+ ctor = { GroupComponent(name) },
+ update = {
+ set(rotation) { this.rotation = it }
+ set(pivotX) { this.pivotX = it }
+ set(pivotY) { this.pivotY = it }
+ set(scaleX) { this.scaleX = it }
+ set(scaleY) { this.scaleY = it }
+ set(translationX) { this.translationX = it }
+ set(translationY) { this.translationY = it }
+ set(clipPathData) { this.clipPathData = it }
+ }
+ ) {
+ children()
+ }
}
}
@Composable
-fun VectorScope.Path(
+fun Path(
pathData: List<PathNode>,
name: String = DefaultPathName,
fill: Brush? = null,
@@ -74,119 +74,58 @@
strokeLineJoin: StrokeJoin = DefaultStrokeLineJoin,
strokeLineMiter: Float = DefaultStrokeLineMiter
) {
- PathComponent(
- name = name,
- pathData = pathData,
- fill = fill,
- fillAlpha = fillAlpha,
- stroke = stroke,
- strokeAlpha = strokeAlpha,
- strokeLineWidth = strokeLineWidth,
- strokeLineJoin = strokeLineJoin,
- strokeLineCap = strokeLineCap,
- strokeLineMiter = strokeLineMiter
- )
+ key(name) {
+ emit<PathComponent, VectorApplier>(
+ ctor = { PathComponent(name) },
+ update = {
+ set(pathData) { this.pathData = it }
+ set(fill) { this.fill = it }
+ set(fillAlpha) { this.fillAlpha = it }
+ set(stroke) { this.stroke = it }
+ set(strokeAlpha) { this.strokeAlpha = it }
+ set(strokeLineWidth) { this.strokeLineWidth = it }
+ set(strokeLineJoin) { this.strokeLineJoin = it }
+ set(strokeLineCap) { this.strokeLineCap = it }
+ set(strokeLineMiter) { this.strokeLineMiter = it }
+ }
+ )
+ }
}
-class VectorScope internal constructor (internal val composer: VectorComposer)
-
@Suppress("NAME_SHADOWING")
internal fun composeVector(
container: VectorComponent,
recomposer: Recomposer,
parent: CompositionReference? = null,
- composable: @Composable VectorScope.(viewportWidth: Float, viewportHeight: Float) -> Unit
+ composable: @Composable (viewportWidth: Float, viewportHeight: Float) -> Unit
): Composition = compositionFor(
- container = container,
- recomposer = recomposer,
- parent = parent,
- composerFactory = { slots, recomposer -> VectorComposer(container.root, slots, recomposer) }
+ container,
+ VectorApplier(container.root),
+ recomposer,
+ parent
).apply {
setContent {
- val composer = currentComposer as VectorComposer
- val scope = VectorScope(composer)
- scope.composable(container.viewportWidth, container.viewportHeight)
+ composable(container.viewportWidth, container.viewportHeight)
}
}
-@OptIn(ComposeCompilerApi::class)
-internal class VectorComposer(
- val root: VNode,
- slotTable: SlotTable,
- recomposer: Recomposer
-) : Composer<VNode>(slotTable, Applier(root, VectorApplyAdapter()), recomposer) {
- inline fun <T : VNode> emit(
- key: Any,
- /*crossinline*/
- ctor: () -> T,
- update: VectorUpdater<VNode>.() -> Unit
- ) {
- startNode(key)
-
- @Suppress("UNCHECKED_CAST")
- val node = if (inserting) {
- ctor().also {
- emitNode(it)
- }
- } else {
- useNode()
- }
-
- VectorUpdater(this, node).update()
- endNode()
+class VectorApplier(root: VNode) : AbstractApplier<VNode>(root) {
+ override fun insert(index: Int, instance: VNode) {
+ current.asGroup().insertAt(index, instance)
}
- inline fun emit(
- key: Any,
- /*crossinline*/
- ctor: () -> GroupComponent,
- update: VectorUpdater<GroupComponent>.() -> Unit,
- children: () -> Unit
- ) {
- startNode(key)
-
- @Suppress("UNCHECKED_CAST")
- val node = if (inserting) {
- ctor().also {
- emitNode(it)
- }
- } else {
- useNode() as GroupComponent
- }
-
- VectorUpdater(this, node).update()
- children()
- endNode()
- }
-}
-
-internal class VectorApplyAdapter : ApplyAdapter<VNode> {
- override fun VNode.start(instance: VNode) {
- // NO-OP
+ override fun remove(index: Int, count: Int) {
+ current.asGroup().remove(index, count)
}
- override fun VNode.insertAt(index: Int, instance: VNode) {
- obtainGroup().insertAt(index, instance)
+ override fun move(from: Int, to: Int, count: Int) {
+ current.asGroup().move(from, to, count)
}
- override fun VNode.removeAt(index: Int, count: Int) {
- obtainGroup().remove(index, count)
- }
-
- override fun VNode.move(from: Int, to: Int, count: Int) {
- obtainGroup().move(from, to, count)
- }
-
- override fun VNode.end(instance: VNode, parent: VNode) {
- // NO-OP
- }
-
- fun VNode.obtainGroup(): GroupComponent {
+ private fun VNode.asGroup(): GroupComponent {
return when (this) {
is GroupComponent -> this
- else -> throw IllegalArgumentException("Cannot only insert VNode into Group")
+ else -> error("Cannot only insert VNode into Group")
}
}
}
-
-typealias VectorUpdater<T> = ComposerUpdater<VNode, T>
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt
index 6973254..6c71636 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/graphics/vector/VectorPainter.kt
@@ -59,7 +59,7 @@
viewportWidth: Float = Float.NaN,
viewportHeight: Float = Float.NaN,
name: String = RootGroupName,
- children: @Composable VectorScope.(viewportWidth: Float, viewportHeight: Float) -> Unit
+ children: @Composable (viewportWidth: Float, viewportHeight: Float) -> Unit
): VectorPainter {
val density = DensityAmbient.current
val widthPx = with(density) { defaultWidth.toPx() }
@@ -137,7 +137,7 @@
defaultHeight: Float,
viewportWidth: Float = defaultWidth,
viewportHeight: Float = defaultHeight,
- children: @Composable VectorScope.(viewportWidth: Float, viewportHeight: Float) -> Unit
+ children: @Composable (viewportWidth: Float, viewportHeight: Float) -> Unit
): VectorComponent {
val vector =
remember(name, viewportWidth, viewportHeight) {
@@ -171,7 +171,7 @@
* the tree structure
*/
@Composable
-private fun VectorScope.RenderVectorGroup(group: VectorGroup) {
+private fun RenderVectorGroup(group: VectorGroup) {
for (vectorNode in group) {
if (vectorNode is VectorPath) {
Path(
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt
index 760e565..8ce0ef6b 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/input/TextInputServiceAndroid.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.text.InputType
import android.view.View
+import android.view.ViewTreeObserver
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import android.view.inputmethod.InputMethodManager
@@ -45,11 +46,31 @@
private var imeAction = ImeAction.Unspecified
private var ic: RecordingInputConnection? = null
+ private var focusedRect: android.graphics.Rect? = null
+
/**
* The editable buffer used for BaseInputConnection.
*/
private lateinit var imm: InputMethodManager
+ private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
+ // focusedRect is null if there is not ongoing text input session. So safe to request
+ // latest focused rectangle whenever global layout has changed.
+ focusedRect?.let { view.requestRectangleOnScreen(it) }
+ }
+
+ init {
+ view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
+ override fun onViewDetachedFromWindow(v: View?) {
+ v?.rootView?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener)
+ }
+
+ override fun onViewAttachedToWindow(v: View?) {
+ v?.rootView?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener)
+ }
+ })
+ }
+
/**
* Creates new input connection.
*/
@@ -104,6 +125,7 @@
editorHasFocus = false
onEditCommand = {}
onImeActionPerformed = {}
+ focusedRect = null
imm.restartInput(view)
editorHasFocus = false
@@ -123,11 +145,22 @@
}
override fun notifyFocusedRect(rect: Rect) {
- view.requestRectangleOnScreen(android.graphics.Rect(
+ focusedRect = android.graphics.Rect(
rect.left.roundToInt(),
rect.top.roundToInt(),
rect.right.roundToInt(),
- rect.bottom.roundToInt()))
+ rect.bottom.roundToInt()
+ )
+
+ // Requesting rectangle too early after obtaining focus may bring view into wrong place
+ // probably due to transient IME inset change. We don't know the correct timing of calling
+ // requestRectangleOnScreen API, so try to call this API only after the IME is ready to
+ // use, i.e. InputConnection has created.
+ // Even if we miss all the timing of requesting rectangle during initial text field focus,
+ // focused rectangle will be requested when software keyboard has shown.
+ if (ic == null) {
+ view.requestRectangleOnScreen(focusedRect)
+ }
}
/**
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiApplier.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiApplier.kt
new file mode 100644
index 0000000..046ab03
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiApplier.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalComposeApi::class)
+package androidx.ui.node
+
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.Applier
+import androidx.compose.ExperimentalComposeApi
+import androidx.ui.core.LayoutNode
+import androidx.ui.viewinterop.AndroidViewHolder
+
+// TODO: evaluate if this class is necessary or not
+private class Stack<T> {
+ private val backing = ArrayList<T>()
+
+ val size: Int get() = backing.size
+
+ fun push(value: T) = backing.add(value)
+ fun pop(): T = backing.removeAt(size - 1)
+ fun peek(): T = backing[size - 1]
+ fun isEmpty() = backing.isEmpty()
+ fun isNotEmpty() = !isEmpty()
+ fun clear() = backing.clear()
+}
+
+class UiApplier(root: Any) : Applier<Any> {
+ private val stack = Stack<Any>()
+ private data class PendingInsert(val index: Int, val instance: Any)
+ // TODO(b/159073250): remove
+ private val pendingInserts = Stack<PendingInsert>()
+
+ private fun invalidNode(node: Any): Nothing =
+ error("Unsupported node type ${node.javaClass.simpleName}")
+
+ override var current: Any = root
+ private set
+
+ override fun down(node: Any) {
+ stack.push(current)
+ current = node
+ }
+
+ override fun up() {
+ val instance = current
+ val parent = stack.pop()
+ current = parent
+ // TODO(lmr): We should strongly consider removing this ViewAdapter concept
+ val adapter = when (instance) {
+ is View -> instance.getViewAdapterIfExists()
+ else -> null
+ }
+ if (pendingInserts.isNotEmpty()) {
+ val pendingInsert = pendingInserts.peek()
+ if (pendingInsert.instance == instance) {
+ val index = pendingInsert.index
+ pendingInserts.pop()
+
+ when (parent) {
+ is ViewGroup ->
+ when (instance) {
+ is View -> {
+ adapter?.willInsert(instance, parent)
+ parent.addView(instance, index)
+ adapter?.didInsert(instance, parent)
+ }
+// is LayoutNode -> {
+// val adaptedView = adapters?.adapt(parent, instance) as? View
+// ?: error(
+// "Could not convert ${
+// instance.javaClass.simpleName
+// } to a View"
+// )
+// adapter?.willInsert(adaptedView, parent)
+// parent.addView(adaptedView, index)
+// adapter?.didInsert(adaptedView, parent)
+// }
+ else -> invalidNode(instance)
+ }
+ is LayoutNode ->
+ when (instance) {
+ is View -> {
+ // Wrap the instance in an AndroidViewHolder, unless the instance
+ // itself is already one.
+ val androidViewHolder =
+ if (instance is AndroidViewHolder) {
+ instance
+ } else {
+ AndroidViewHolder(instance.context).apply {
+ view = instance
+ }
+ }
+
+ parent.insertAt(index, androidViewHolder.toLayoutNode())
+ }
+ is LayoutNode -> parent.insertAt(index, instance)
+ else -> invalidNode(instance)
+ }
+ else -> invalidNode(parent)
+ }
+ return
+ }
+ }
+ if (parent is ViewGroup)
+ adapter?.didUpdate(instance as View, parent)
+ }
+
+ override fun insert(index: Int, instance: Any) {
+ pendingInserts.push(
+ PendingInsert(
+ index,
+ instance
+ )
+ )
+ }
+
+ override fun remove(index: Int, count: Int) {
+ when (val node = current) {
+ is ViewGroup -> node.removeViews(index, count)
+ is LayoutNode -> node.removeAt(index, count)
+ else -> invalidNode(node)
+ }
+ }
+
+ override fun move(from: Int, to: Int, count: Int) {
+ when (val node = current) {
+ is ViewGroup -> {
+ if (from > to) {
+ var currentFrom = from
+ var currentTo = to
+ repeat(count) {
+ val view = node.getChildAt(currentFrom)
+ node.removeViewAt(currentFrom)
+ node.addView(view, currentTo)
+ currentFrom++
+ currentTo++
+ }
+ } else {
+ repeat(count) {
+ val view = node.getChildAt(from)
+ node.removeViewAt(from)
+ node.addView(view, to - 1)
+ }
+ }
+ }
+ is LayoutNode -> {
+ node.move(from, to, count)
+ }
+ else -> invalidNode(node)
+ }
+ }
+
+ override fun reset() {
+ stack.clear()
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiComposer.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiComposer.kt
deleted file mode 100644
index a0686f6..0000000
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/node/UiComposer.kt
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:OptIn(ExperimentalComposeApi::class, ComposeCompilerApi::class)
-package androidx.ui.node
-
-import android.content.Context
-import android.view.View
-import android.view.ViewGroup
-import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
-import androidx.compose.ComposeCompilerApi
-import androidx.compose.Composer
-import androidx.compose.ComposerUpdater
-import androidx.compose.ExperimentalComposeApi
-import androidx.compose.FrameManager
-import androidx.compose.Recomposer
-import androidx.compose.SlotTable
-import androidx.ui.core.LayoutNode
-import androidx.ui.viewinterop.AndroidViewHolder
-
-// TODO: evaluate if this class is necessary or not
-private class Stack<T> {
- private val backing = ArrayList<T>()
-
- val size: Int get() = backing.size
-
- fun push(value: T) = backing.add(value)
- fun pop(): T = backing.removeAt(size - 1)
- fun peek(): T = backing[size - 1]
- fun isEmpty() = backing.isEmpty()
- fun isNotEmpty() = !isEmpty()
- fun clear() = backing.clear()
-}
-
-private fun invalidNode(node: Any): Nothing =
- error("Unsupported node type ${node.javaClass.simpleName}")
-
-internal class UiApplyAdapter : ApplyAdapter<Any> {
- private data class PendingInsert(val index: Int, val instance: Any)
-
- private val pendingInserts =
- Stack<PendingInsert>()
-
- override fun Any.start(instance: Any) {}
- override fun Any.insertAt(index: Int, instance: Any) {
- pendingInserts.push(
- PendingInsert(
- index,
- instance
- )
- )
- }
-
- override fun Any.removeAt(index: Int, count: Int) {
- when (this) {
- is ViewGroup -> removeViews(index, count)
- is LayoutNode -> removeAt(index, count)
- else -> invalidNode(this)
- }
- }
-
- override fun Any.move(from: Int, to: Int, count: Int) {
- when (this) {
- is ViewGroup -> {
- if (from > to) {
- var currentFrom = from
- var currentTo = to
- repeat(count) {
- val view = getChildAt(currentFrom)
- removeViewAt(currentFrom)
- addView(view, currentTo)
- currentFrom++
- currentTo++
- }
- } else {
- repeat(count) {
- val view = getChildAt(from)
- removeViewAt(from)
- addView(view, to - 1)
- }
- }
- }
- is LayoutNode -> {
- move(from, to, count)
- }
- else -> invalidNode(this)
- }
- }
-
- override fun Any.end(instance: Any, parent: Any) {
- val adapter = when (instance) {
- is View -> instance.getViewAdapterIfExists()
- else -> null
- }
- if (pendingInserts.isNotEmpty()) {
- val pendingInsert = pendingInserts.peek()
- if (pendingInsert.instance == instance) {
- val index = pendingInsert.index
- pendingInserts.pop()
-
- when (parent) {
- is ViewGroup ->
- when (instance) {
- is View -> {
- adapter?.willInsert(instance, parent)
- parent.addView(instance, index)
- adapter?.didInsert(instance, parent)
- }
-// is LayoutNode -> {
-// val adaptedView = adapters?.adapt(parent, instance) as? View
-// ?: error(
-// "Could not convert ${
-// instance.javaClass.simpleName
-// } to a View"
-// )
-// adapter?.willInsert(adaptedView, parent)
-// parent.addView(adaptedView, index)
-// adapter?.didInsert(adaptedView, parent)
-// }
- else -> invalidNode(instance)
- }
- is LayoutNode ->
- when (instance) {
- is View -> {
- // Wrap the instance in an AndroidViewHolder, unless the instance
- // itself is already one.
- val androidViewHolder =
- if (instance is AndroidViewHolder) {
- instance
- } else {
- AndroidViewHolder(instance.context).apply {
- view = instance
- }
- }
-
- parent.insertAt(index, androidViewHolder.toLayoutNode())
- }
- is LayoutNode -> parent.insertAt(index, instance)
- else -> invalidNode(instance)
- }
- else -> invalidNode(parent)
- }
- return
- }
- }
- if (parent is ViewGroup)
- adapter?.didUpdate(instance as View, parent)
- }
-}
-
-class UiComposer(
- val context: Context,
- val root: Any,
- slotTable: SlotTable,
- recomposer: Recomposer
-) : Composer<Any>(
- slotTable,
- Applier(
- root,
- UiApplyAdapter()
- ),
- recomposer
-) {
- init {
- FrameManager.ensureStarted()
- }
-
- @Suppress("UNCHECKED_CAST")
- inline fun <T : View> emit(
- key: Any,
- /*crossinline*/
- ctor: (context: Context) -> T,
- update: UiUpdater<T>.() -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor(context).also { emitNode(it) }
- else useNode() as T
- UiUpdater(this, node).update()
- endNode()
- }
-
- @Suppress("UNCHECKED_CAST")
- inline fun <T : ViewGroup> emit(
- key: Any,
- /*crossinline*/
- ctor: (context: Context) -> T,
- update: UiUpdater<T>.() -> Unit,
- children: () -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor(context).also { emitNode(it) }
- else useNode() as T
- UiUpdater(this, node).update()
- children()
- endNode()
- }
-
- // There is a compilation error if I change T -> LayoutNode, so I
- // just suppressed the warning
- @Suppress("UNCHECKED_CAST", "FINAL_UPPER_BOUND")
- inline fun <T : LayoutNode> emit(
- key: Any,
- /*crossinline*/
- ctor: () -> T,
- update: UiUpdater<T>.() -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor().also { emitNode(it) }
- else useNode() as T
- UiUpdater(this, node).update()
- endNode()
- }
-
- // There is a compilation error if I change T -> LayoutNode, so I
- // just suppressed the warning
- @Suppress("UNCHECKED_CAST", "FINAL_UPPER_BOUND")
- inline fun <T : LayoutNode> emit(
- key: Any,
- /*crossinline*/
- ctor: () -> T,
- update: UiUpdater<T>.() -> Unit,
- children: () -> Unit
- ) {
- startNode(key)
- val node = if (inserting) ctor().also { emitNode(it) }
- else useNode() as T
- UiUpdater(this, node).update()
- children()
- endNode()
- }
-}
-
-typealias UiUpdater<T> = ComposerUpdater<Any, T>
\ No newline at end of file
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/semantics/Semantics.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/semantics/Semantics.kt
deleted file mode 100644
index f1cebac..0000000
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/semantics/Semantics.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package androidx.ui.semantics
-
-import androidx.compose.Composable
-import androidx.ui.core.PassThroughLayout
-import androidx.ui.core.Modifier
-import androidx.ui.core.semantics.semantics
-
-@Deprecated("Semantics() is deprecated. Use Modifier.semantics() instead.")
-@Composable
-fun Semantics(
- /**
- * Legacy parameter, no longer has any effect.
- */
- @Suppress("UNUSED_PARAMETER") container: Boolean = false,
- /**
- * Whether the semantic information provided by the owning component and
- * all of its descendants should be treated as one logical entity.
- *
- * If set to true, the descendants of the owning component's
- * [SemanticsNode] will merge their semantic information into the
- * [SemanticsNode] representing the owning component.
- */
- mergeAllDescendants: Boolean = false,
- properties: (SemanticsPropertyReceiver.() -> Unit)? = null,
- children: @Composable () -> Unit
-) {
- @Suppress("DEPRECATION")
- PassThroughLayout(
- Modifier.semantics(
- applyToChildLayoutNode = true,
- mergeAllDescendants = mergeAllDescendants,
- properties = properties),
- children)
-}
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt
index 119ce7a..7187ac5 100644
--- a/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/ComposedView.kt
@@ -26,6 +26,9 @@
import androidx.compose.currentComposer
import androidx.ui.core.Modifier
import androidx.ui.core.materialize
+import androidx.compose.emit
+import androidx.ui.core.ContextAmbient
+import androidx.ui.node.UiApplier
/**
* Composes an Android [View] given a layout resource [resId]. The method handles the inflation
@@ -42,10 +45,15 @@
modifier: Modifier = Modifier,
postInflationCallback: (View) -> Unit = { _ -> }
) {
- AndroidViewHolder(
- postInflationCallback = postInflationCallback,
- resId = resId,
- modifier = currentComposer.materialize(modifier)
+ val context = ContextAmbient.current
+ val materialized = currentComposer.materialize(modifier)
+ emit<AndroidViewHolder, UiApplier>(
+ ctor = { AndroidViewHolder(context) },
+ update = {
+ set(postInflationCallback) { this.postInflationCallback = it }
+ set(resId) { this.resId = it }
+ set(materialized) { this.modifier = it }
+ }
)
}
@@ -57,7 +65,15 @@
*/
@Composable
fun AndroidView(view: View, modifier: Modifier = Modifier) {
- AndroidViewHolder(view = view, modifier = currentComposer.materialize(modifier))
+ val context = ContextAmbient.current
+ val materialized = currentComposer.materialize(modifier)
+ emit<AndroidViewHolder, UiApplier>(
+ ctor = { AndroidViewHolder(context) },
+ update = {
+ set(view) { this.view = it }
+ set(materialized) { this.modifier = it }
+ }
+ )
}
// Open to be mockable in tests.
diff --git a/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/EmitView.kt b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/EmitView.kt
new file mode 100644
index 0000000..3b08b43
--- /dev/null
+++ b/ui/ui-core/src/androidMain/kotlin/androidx/ui/viewinterop/EmitView.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.viewinterop
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.Composable
+import androidx.compose.emit
+import androidx.ui.core.ContextAmbient
+import androidx.ui.node.UiApplier
+
+/**
+ * Emit a view into the current composition.
+ *
+ * @sample androidx.ui.core.samples.EmitViewButtonSample
+ *
+ * @param ctor The constructor of the view with a single [Context] parameter.
+ * @param update A function which will execute when the composition is applied, with the emitted
+ * view instance passed in. This function is expected to be used to handle the "update" logic to
+ * handle any changes.
+ */
+@Composable
+fun <T : View> emitView(
+ ctor: (Context) -> T,
+ update: (T) -> Unit
+) {
+ val context = ContextAmbient.current
+ emit<T, UiApplier>(
+ ctor = { ctor(context) },
+ update = {
+ reconcile(update)
+ }
+ )
+}
+
+/**
+ * Emit a ViewGroup into the current composition, with the emitted nodes of [children] as the
+ * content.
+ *
+ * @sample androidx.ui.core.samples.EmitViewLinearLayoutSample
+ *
+ * @param ctor The constructor of the view with a single [Context] parameter.
+ * @param update A function which will execute when the composition is applied, with the emitted
+ * view instance passed in. This function is expected to be used to handle the "update" logic to
+ * handle any changes.
+ * @param children the composable content that will emit the "children" of this view.
+ */
+@Composable
+fun <T : ViewGroup> emitView(
+ ctor: (Context) -> T,
+ update: (T) -> Unit,
+ children: @Composable () -> Unit
+) {
+ val context = ContextAmbient.current
+ emit<T, UiApplier>(
+ ctor = { ctor(context) },
+ update = {
+ reconcile(update)
+ },
+ children = children
+ )
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt
index 8da03e3..5baa9ce 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/autofill/AndroidAutofillTest.kt
@@ -17,14 +17,15 @@
package androidx.ui.autofill
import android.app.Activity
-import androidx.ui.geometry.Rect
+import android.graphics.Rect as AndroidRect
import android.view.View
import android.view.autofill.AutofillManager
import androidx.test.filters.SmallTest
import androidx.ui.ComposeUiRobolectricTestRunner
+import androidx.ui.core.toComposeRect
+import androidx.ui.geometry.Rect
import com.google.common.truth.Truth.assertThat
import org.junit.Before
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
@@ -69,7 +70,6 @@
assertThat(view.importantForAutofill).isEqualTo(View.IMPORTANT_FOR_AUTOFILL_YES)
}
- @Ignore("b/159210000")
@Test
fun requestAutofillForNode_calls_notifyViewEntered() {
// Arrange.
@@ -121,8 +121,8 @@
val viewExitedStats = mutableListOf<NotifyViewExited>()
@Implementation
- fun notifyViewEntered(view: View, virtualId: Int, rect: Rect) {
- viewEnteredStats += NotifyViewEntered(view, virtualId, rect)
+ fun notifyViewEntered(view: View, virtualId: Int, rect: AndroidRect) {
+ viewEnteredStats += NotifyViewEntered(view, virtualId, rect.toComposeRect())
}
@Implementation
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt
index 2d3b191..a724024 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/ComposedModifierTest.kt
@@ -17,15 +17,14 @@
package androidx.ui.core
import androidx.compose.Applier
-import androidx.compose.ApplyAdapter
import androidx.compose.Composable
import androidx.compose.Composer
-import androidx.compose.CompositionFrameClock
import androidx.compose.ExperimentalComposeApi
import androidx.compose.InternalComposeApi
import androidx.compose.Recomposer
import androidx.compose.SlotTable
import androidx.compose.currentComposer
+import androidx.compose.dispatch.MonotonicFrameClock
import androidx.compose.invalidate
import androidx.compose.remember
import androidx.compose.withRunningRecomposer
@@ -49,8 +48,6 @@
@OptIn(InternalComposeApi::class)
class ComposedModifierTest {
- private val composer: Composer<*> get() = error("should not be called")
-
/**
* Confirm that a [composed] modifier correctly constructs separate instances when materialized
*/
@@ -201,29 +198,27 @@
}
}
-@OptIn(InternalComposeApi::class)
+@OptIn(InternalComposeApi::class, ExperimentalComposeApi::class)
private fun compose(
recomposer: Recomposer,
block: @Composable () -> Unit
-): Composer<Unit> = UnitComposer(recomposer).apply {
- compose(block)
- applyChanges()
- slotTable.verifyWellFormed()
+): Composer<Unit> {
+ return Composer(
+ SlotTable(),
+ EmptyApplier(),
+ recomposer
+ ).apply {
+ composeRoot {
+ @Suppress("UNCHECKED_CAST")
+ val fn = block as (Composer<*>, Int, Int) -> Unit
+ fn(this, 0, 0)
+ }
+ applyChanges()
+ slotTable.verifyWellFormed()
+ }
}
-/**
- * This ApplyAdapter does nothing. These tests only confirm modifier materialization.
- */
-@OptIn(ExperimentalComposeApi::class)
-private object UnitApplierAdapter : ApplyAdapter<Unit> {
- override fun Unit.start(instance: Unit) {}
- override fun Unit.insertAt(index: Int, instance: Unit) {}
- override fun Unit.removeAt(index: Int, count: Int) {}
- override fun Unit.move(from: Int, to: Int, count: Int) {}
- override fun Unit.end(instance: Unit, parent: Unit) {}
-}
-
-private class TestFrameClock : CompositionFrameClock {
+private class TestFrameClock : MonotonicFrameClock {
private val frameCh = Channel<Long>()
@@ -235,16 +230,18 @@
}
@OptIn(ExperimentalComposeApi::class)
-private class UnitComposer(recomposer: Recomposer) : Composer<Unit>(
- SlotTable(),
- Applier(Unit, UnitApplierAdapter),
- recomposer
-) {
- fun compose(composable: @Composable () -> Unit) {
- composeRoot {
- @Suppress("UNCHECKED_CAST")
- val fn = composable as (Composer<*>, Int, Int) -> Unit
- fn(this@UnitComposer, 0, 0)
- }
+class EmptyApplier : Applier<Unit> {
+ override val current: Unit = Unit
+ override fun down(node: Unit) {}
+ override fun up() {}
+ override fun insert(index: Int, instance: Unit) {
+ error("Unexpected")
}
-}
\ No newline at end of file
+ override fun remove(index: Int, count: Int) {
+ error("Unexpected")
+ }
+ override fun move(from: Int, to: Int, count: Int) {
+ error("Unexpected")
+ }
+ override fun reset() {}
+}
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt
index 7603287..03464d8 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/LayoutNodeTest.kt
@@ -31,6 +31,7 @@
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
+import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
@@ -656,6 +657,45 @@
assertFalse(layoutNode.coordinates.isAttached)
}
+ // The LayoutNodeWrapper should be reused when it has been replaced with the same type
+ @Test
+ fun layoutNodeWrapperSameWithReplacementModifier() {
+ val layoutNode = LayoutNode()
+ val drawModifier = Modifier.drawBehind { }
+
+ layoutNode.modifier = drawModifier
+ val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+ assertFalse(oldLayoutNodeWrapper.isAttached)
+
+ layoutNode.attach(mockOwner())
+ assertTrue(oldLayoutNodeWrapper.isAttached)
+
+ layoutNode.modifier = Modifier.drawBehind { }
+ val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+ assertSame(newLayoutNodeWrapper, oldLayoutNodeWrapper)
+ }
+
+ // The LayoutNodeWrapper should be reused when it has been replaced with the same type,
+ // even with multiple LayoutNodeWrappers for one modifier.
+ @Test
+ fun layoutNodeWrapperSameWithReplacementMultiModifier() {
+ class TestModifier : DrawModifier, DrawLayerModifier {
+ override fun ContentDrawScope.draw() {
+ drawContent()
+ }
+ }
+ val layoutNode = LayoutNode()
+
+ layoutNode.modifier = TestModifier()
+ val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+ val oldLayoutNodeWrapper2 = oldLayoutNodeWrapper.wrapped
+ layoutNode.modifier = TestModifier()
+ val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
+ val newLayoutNodeWrapper2 = newLayoutNodeWrapper.wrapped
+ assertSame(newLayoutNodeWrapper, oldLayoutNodeWrapper)
+ assertSame(newLayoutNodeWrapper2, oldLayoutNodeWrapper2)
+ }
+
// The LayoutNodeWrapper should be detached when it has been replaced.
@Test
fun layoutNodeWrapperAttachedWhenLayoutNodeAttached() {
@@ -669,7 +709,7 @@
layoutNode.attach(mockOwner())
assertTrue(oldLayoutNodeWrapper.isAttached)
- layoutNode.modifier = Modifier.drawBehind { }
+ layoutNode.modifier = Modifier.drawLayer()
val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
assertTrue(newLayoutNodeWrapper.isAttached)
assertFalse(oldLayoutNodeWrapper.isAttached)
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt
index cd4a7fc..1de3982 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/DragSlopExceededGestureFilterTest.kt
@@ -14,11 +14,18 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalPointerInput::class)
+@file:Suppress("PrivatePropertyName")
+
package androidx.ui.core.gesture
import androidx.ui.core.Direction
import androidx.ui.core.PointerEventPass
import androidx.ui.core.consumeDownChange
+import androidx.ui.core.gesture.scrollorientationlocking.InternalScrollOrientationLocker
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ScrollOrientationLocker
+import androidx.ui.core.gesture.scrollorientationlocking.ShareScrollOrientationLockerEvent
import androidx.ui.testutils.consume
import androidx.ui.testutils.down
import androidx.ui.testutils.invokeOverAllPasses
@@ -29,6 +36,7 @@
import androidx.ui.unit.Duration
import androidx.ui.unit.milliseconds
import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.mock
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -66,8 +74,9 @@
canDragDirections.clear()
filter =
DragSlopExceededGestureFilter(TestTouchSlop.toFloat())
- filter.canDrag = canDrag
+ filter.setDraggableData(null, canDrag)
filter.onDragSlopExceeded = onDragSlopExceeded
+ filter.scrollOrientationLocker = ScrollOrientationLocker(mock())
}
// Verify the circumstances under which canDrag should not be called.
@@ -881,6 +890,219 @@
assertThat(onDragSlopExceededCallCount).isEqualTo(2)
}
+ // Orientation tests
+
+ // Tests that verify correct behavior when orientation is set.
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementVertical_canDragNotCalled() {
+ filter.setDraggableData(Orientation.Horizontal, canDrag)
+
+ val down = down(0)
+ filter::onPointerInput.invokeOverAllPasses(down)
+ val move1 = down.moveBy(Duration(milliseconds = 10), 0f, 1f)
+ filter::onPointerInput.invokeOverAllPasses(move1)
+ val move2 = down.moveBy(Duration(milliseconds = 10), 0f, -1f)
+ filter::onPointerInput.invokeOverAllPasses(move2)
+
+ assertThat(canDragDirections).isEmpty()
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsHorizontal_canDragNotCalled() {
+ filter.setDraggableData(Orientation.Vertical, canDrag)
+
+ val down = down(0)
+ filter::onPointerInput.invokeOverAllPasses(down)
+ val move1 = down.moveBy(Duration(milliseconds = 10), 1f, 0f)
+ filter::onPointerInput.invokeOverAllPasses(move1)
+ val move2 = down.moveBy(Duration(milliseconds = 10), -1f, 0f)
+ filter::onPointerInput.invokeOverAllPasses(move2)
+
+ assertThat(canDragDirections).isEmpty()
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementHorizontal_canDragCalled() {
+ filter.setDraggableData(Orientation.Horizontal, canDrag)
+
+ val down = down(0)
+ filter::onPointerInput.invokeOverAllPasses(down)
+ val move1 = down.moveBy(Duration(milliseconds = 10), 1f, 0f)
+ filter::onPointerInput.invokeOverAllPasses(move1)
+ val move2 = down.moveBy(Duration(milliseconds = 10), -1f, 0f)
+ filter::onPointerInput.invokeOverAllPasses(move2)
+
+ // 2 for each because canDrag is currently checked on both postUp and postDown
+ assertThat(canDragDirections.filter { it == Direction.LEFT }).hasSize(2)
+ assertThat(canDragDirections.filter { it == Direction.RIGHT }).hasSize(2)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsVertical_canDragCalled() {
+ filter.setDraggableData(Orientation.Vertical, canDrag)
+
+ val down = down(0)
+ filter::onPointerInput.invokeOverAllPasses(down)
+ val move1 = down.moveBy(Duration(milliseconds = 10), 0f, 1f)
+ filter::onPointerInput.invokeOverAllPasses(move1)
+ val move2 = down.moveBy(Duration(milliseconds = 10), 0f, -1f)
+ filter::onPointerInput.invokeOverAllPasses(move2)
+
+ // 2 for each because canDrag is currently checked on both postUp and postDown
+ assertThat(canDragDirections.filter { it == Direction.UP }).hasSize(2)
+ assertThat(canDragDirections.filter { it == Direction.DOWN }).hasSize(2)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMoveLeftPassedSlop_onTouchSlopExceededCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, -1, 0, 1)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMoveUpPassedSlop_onTouchSlopExceededNotCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, 0, -1, 0)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMoveRightPassedSlop_onTouchSlopExceededCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, 1, 0, 1)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMoveDownPassedSlop_onTouchSlopExceededNotCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Horizontal, 0, 1, 0)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMoveLeftPassedSlop_onTouchSlopExceededNotCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, -1, 0, 0)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMoveUpPassedSlop_onTouchSlopExceededCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, 0, -1, 1)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMoveRightPassedSlop_onTouchSlopExceededNotCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, 1, 0, 0)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMoveDownPassedSlop_onTouchSlopExceededCalled() {
+ onPointerInput_filterHasOrientationMovePassedSlop(Orientation.Vertical, 0, 1, 1)
+ }
+
+ private fun onPointerInput_filterHasOrientationMovePassedSlop(
+ filterOrientation: Orientation,
+ horizontalDirection: Int,
+ verticalDirection: Int,
+ expectecdOnDragSlopExceededCallCount: Int
+ ) {
+ val beyondSlop = TestTouchSlop + TinyNum
+
+ filter.setDraggableData(filterOrientation, canDrag)
+
+ val down = down(0)
+ filter::onPointerInput.invokeOverAllPasses(down)
+ val move = down.moveBy(
+ Duration(milliseconds = 100),
+ horizontalDirection * beyondSlop,
+ verticalDirection * beyondSlop
+ )
+ filter::onPointerInput.invokeOverAllPasses(move)
+
+ assertThat(onDragSlopExceededCallCount).isEqualTo(expectecdOnDragSlopExceededCallCount)
+ }
+
+ @Test
+ fun onPointerInput_filterHorizontalPointerVerticalMovesLeftPastSlop_callBackNotCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Horizontal, Orientation.Vertical, -1, 0, 0
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterHorizontalPointerVerticalMovesRightPastSlop_callBackNotCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Horizontal, Orientation.Vertical, 1, 0, 0
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterHorizontalPointerHorizontalMovesLeftPastSlop_callBackCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Horizontal, Orientation.Horizontal, -1, 0, 1
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterHorizontalPointerHorizontallMovesRightPastSlop_callBackCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Horizontal, Orientation.Horizontal, 1, 0, 1
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterVerticalPointerHorizontalMovesUpPastSlop_callBackNotCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Vertical, Orientation.Horizontal, 0, -1, 0
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterVerticalPointerHorizontalMovesDownPastSlop_callBackNotCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Vertical, Orientation.Horizontal, 0, 1, 0
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterVerticalPointerVerticalMovesUpPastSlop_callBackCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Vertical, Orientation.Vertical, 0, -1, 1
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterVerticalPointerVerticalMovesDownPastSlop_callBackCalled() {
+ onPointerInput_pointerIsLockedMovesPassedSlop(
+ Orientation.Vertical, Orientation.Vertical, 0, 1, 1
+ )
+ }
+
+ private fun onPointerInput_pointerIsLockedMovesPassedSlop(
+ filterOrientation: Orientation,
+ lockedOrientation: Orientation,
+ horizontalDirection: Int,
+ verticalDirection: Int,
+ expectedOnDragSlopExceededCallCount: Int
+ ) {
+ val beyondSlop = TestTouchSlop + TinyNum
+
+ filter.onInit(mock())
+ val scrollOrientationLocker = InternalScrollOrientationLocker()
+ filter::onCustomEvent.invokeOverAllPasses(
+ ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+ )
+
+ filter.setDraggableData(filterOrientation, canDrag)
+
+ val down = down(0)
+ filter::onPointerInput.invokeOverAllPasses(down)
+ val move = down.moveBy(
+ Duration(milliseconds = 100),
+ horizontalDirection * beyondSlop,
+ verticalDirection * beyondSlop
+ )
+ scrollOrientationLocker.attemptToLockPointers(listOf(move), lockedOrientation)
+
+ filter::onPointerInput.invokeOverAllPasses(move)
+
+ assertThat(onDragSlopExceededCallCount).isEqualTo(expectedOnDragSlopExceededCallCount)
+ }
+
// Verification that cancellation behavior is correct.
@Test
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
index df409af..29dcf18 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/RawDragGestureFilterTest.kt
@@ -16,9 +16,13 @@
package androidx.ui.core.gesture
+import androidx.ui.core.CustomEventDispatcher
import androidx.ui.core.PointerEventPass
import androidx.ui.core.anyPositionChangeConsumed
import androidx.ui.core.consumePositionChange
+import androidx.ui.core.gesture.scrollorientationlocking.InternalScrollOrientationLocker
+import androidx.ui.core.gesture.scrollorientationlocking.Orientation
+import androidx.ui.core.gesture.scrollorientationlocking.ShareScrollOrientationLockerEvent
import androidx.ui.geometry.Offset
import androidx.ui.testutils.consume
import androidx.ui.testutils.down
@@ -31,6 +35,11 @@
import androidx.ui.unit.IntSize
import androidx.ui.unit.milliseconds
import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.argumentCaptor
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.reset
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,6 +57,7 @@
private lateinit var filter: RawDragGestureFilter
private lateinit var dragObserver: MockDragObserver
private lateinit var log: MutableList<LogItem>
+ private lateinit var customEventDispatcher: CustomEventDispatcher
private var dragStartBlocked = true
@Before
@@ -57,6 +67,8 @@
filter = RawDragGestureFilter()
filter.canStartDragging = { !dragStartBlocked }
filter.dragObserver = dragObserver
+ customEventDispatcher = mock()
+ filter.onInit(customEventDispatcher)
}
// Verify the circumstances under which onStart/OnDrag should not be called.
@@ -371,11 +383,14 @@
) {
log.clear()
- var change = down(0, 0.milliseconds)
+ var time = 0.milliseconds
+
+ var change = down(0, time)
filter::onPointerInput.invokeOverAllPasses(change)
dragStartBlocked = false
repeat(11) {
+ time += 10.milliseconds
change = change.moveBy(
10.milliseconds,
incrementPerMilliX,
@@ -384,7 +399,8 @@
filter::onPointerInput.invokeOverAllPasses(change)
}
- change = change.up(20.milliseconds)
+ time += 10.milliseconds
+ change = change.up(time)
filter::onPointerInput.invokeOverAllPasses(change)
val loggedStops = log.filter { it.methodName == "onStop" }
@@ -575,6 +591,440 @@
.isEqualTo(Offset(3f, 4f))
}
+ @Test
+ fun onPointerInput_hasOrientationDownEvent_customEventDispatchedOnceDuringInitialDown() {
+
+ // Arrange
+
+ filter.orientation = Orientation.Vertical
+
+ val down = down(0)
+
+ // Act / Verify 1
+
+ filter::onPointerInput.invokeOverPasses(down, PointerEventPass.InitialDown)
+ argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ assertThat(allValues).hasSize(1)
+ assertThat(allValues.first().scrollOrientationLocker).isNotNull()
+ }
+
+ reset(customEventDispatcher)
+
+ // Act / Verify 1
+ filter::onPointerInput.invokeOverPasses(
+ down,
+ PointerEventPass.PreUp,
+ PointerEventPass.PreDown,
+ PointerEventPass.PostUp,
+ PointerEventPass.PostDown
+ )
+ verifyNoMoreInteractions(customEventDispatcher)
+ }
+
+ @Test
+ fun onPointerInput_hasOrientationDownUpDown_customEventDispatchedTwiceWithDifferentLocker() {
+ filter.orientation = Orientation.Vertical
+
+ val downA = down(0)
+ val upA = downA.up(1.milliseconds)
+ val downB = down(1, 2.milliseconds)
+
+ filter::onPointerInput.invokeOverAllPasses(downA)
+
+ val locker1 = argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+
+ assertThat(allValues).hasSize(1)
+ allValues.first().scrollOrientationLocker
+ }
+
+ filter::onPointerInput.invokeOverAllPasses(upA)
+ reset(customEventDispatcher)
+ filter::onPointerInput.invokeOverAllPasses(downB)
+
+ val locker2 = argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+
+ assertThat(allValues).hasSize(1)
+ allValues.first().scrollOrientationLocker
+ }
+
+ assertThat(locker1).isNotEqualTo(locker2)
+
+ verifyNoMoreInteractions(customEventDispatcher)
+ }
+
+ // The below tests verify correct behavior in relation to scroll orientation locking.
+
+ @Test
+ fun onPointerInput_filterHorizontalPointerLockedToVertical_noStart() {
+ onPointerInput_differentOrientations(
+ Orientation.Vertical,
+ Orientation.Horizontal
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterVerticalPointerLockedToHorizontal_noStart() {
+ onPointerInput_differentOrientations(
+ Orientation.Horizontal,
+ Orientation.Vertical
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterHorizontalPointerLockedToHorizontal_start() {
+ onPointerInput_differentOrientations(
+ Orientation.Horizontal,
+ Orientation.Horizontal
+ )
+ }
+
+ @Test
+ fun onPointerInput_filterVerticalPointerLockedToVertical_start() {
+ onPointerInput_differentOrientations(
+ Orientation.Vertical,
+ Orientation.Vertical
+ )
+ }
+
+ private fun onPointerInput_differentOrientations(
+ filterOrientation: Orientation,
+ lockedOrientation: Orientation
+ ) {
+
+ // Arrange
+
+ filter.orientation = filterOrientation
+ dragStartBlocked = false
+
+ val scrollOrientationLocker = InternalScrollOrientationLocker()
+
+ filter::onCustomEvent.invokeOverAllPasses(
+ ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+ )
+
+ val down = down(0)
+ val move = down.moveBy(1.milliseconds, 3f, 5f)
+
+ filter::onPointerInput.invokeOverAllPasses(down)
+
+ scrollOrientationLocker.attemptToLockPointers(listOf(move), lockedOrientation)
+
+ // Act
+ filter::onPointerInput.invokeOverAllPasses(move)
+
+ // Assert
+ if (filterOrientation == lockedOrientation) {
+ assertThat(log.filter { it.methodName == "onStart" }).hasSize(1)
+ // onDrag get's called twice because it is called during PostUp and PostDown and nothing
+ // consumed the drag distance.
+ assertThat(log.filter { it.methodName == "onDrag" }).hasSize(2)
+ } else {
+ assertThat(log.filter { it.methodName == "onStart" }).isEmpty()
+ assertThat(log.filter { it.methodName == "onDrag" }).isEmpty()
+ }
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementIsHorizontal_locksHorizontal() {
+ onPointerInput_mayLockPointers(false, Orientation.Horizontal, 1f, 0f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsVertical_locksVertical() {
+ onPointerInput_mayLockPointers(false, Orientation.Vertical, 0f, 1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementIsBoth_locksHorizontal() {
+ onPointerInput_mayLockPointers(false, Orientation.Horizontal, -1f, -1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsBoth_locksVertical() {
+ onPointerInput_mayLockPointers(false, Orientation.Vertical, -1f, -1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementIsHorizontalBlocked_locksHorizontal() {
+ onPointerInput_mayLockPointers(true, Orientation.Horizontal, 1f, 0f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsVerticalBlocked_locksVertical() {
+ onPointerInput_mayLockPointers(true, Orientation.Vertical, 0f, 1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementIsBothBlocked_locksHorizontal() {
+ onPointerInput_mayLockPointers(true, Orientation.Horizontal, -1f, -1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsBothBlocked_locksVertical() {
+ onPointerInput_mayLockPointers(true, Orientation.Vertical, -1f, -1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsHorizontalMovementIsVertical_locksNone() {
+ onPointerInput_mayLockPointers(false, Orientation.Horizontal, 0f, -1f)
+ }
+
+ @Test
+ fun onPointerInput_filterIsVerticalMovementIsHorizontal_locksNone() {
+ onPointerInput_mayLockPointers(false, Orientation.Vertical, -1f, 0f)
+ }
+
+ private fun onPointerInput_mayLockPointers(
+ blocked: Boolean,
+ filterOrientation: Orientation,
+ dx: Float,
+ dy: Float
+ ) {
+
+ // Arrange
+
+ val otherOrientation =
+ when (filterOrientation) {
+ Orientation.Vertical -> Orientation.Horizontal
+ Orientation.Horizontal -> Orientation.Vertical
+ }
+
+ filter.orientation = filterOrientation
+
+ dragStartBlocked = blocked
+
+ val scrollOrientationLocker = InternalScrollOrientationLocker()
+
+ filter::onCustomEvent.invokeOverAllPasses(
+ ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+ )
+
+ val down = down(0)
+ val move = down.moveBy(1.milliseconds, dx, dy)
+
+ filter::onPointerInput.invokeOverAllPasses(down)
+
+ // Act
+ filter::onPointerInput.invokeOverAllPasses(move)
+
+ // Assert
+ if (!blocked && (filterOrientation == Orientation.Horizontal && dx != 0f ||
+ filterOrientation == Orientation.Vertical && dy != 0f)
+ ) {
+ assertThat(scrollOrientationLocker.getPointersFor(listOf(move), otherOrientation))
+ .hasSize(0)
+ } else {
+ assertThat(scrollOrientationLocker.getPointersFor(listOf(move), otherOrientation))
+ .hasSize(1)
+ }
+ }
+
+ @Test
+ fun onPointerInput_Hori3Pointers1LockedVert2Average0__onStartAndOnDragNotCalled() {
+
+ // Arrange
+
+ filter.orientation = Orientation.Horizontal
+
+ val scrollOrientationLocker = InternalScrollOrientationLocker()
+ filter::onCustomEvent.invokeOverAllPasses(
+ ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+ )
+
+ val pointers = arrayOf(down(0), down(1), down(2))
+ filter::onPointerInput.invokeOverAllPasses(*pointers)
+
+ dragStartBlocked = false
+
+ // This pointer is going to be locked to vertical.
+ pointers[0] =
+ pointers[0].moveBy(
+ 100.milliseconds,
+ 100f,
+ 0f
+ )
+ scrollOrientationLocker.attemptToLockPointers(listOf(pointers[0]), Orientation.Vertical)
+
+ // These pointers average to no movement.
+ pointers[1] =
+ pointers[1].moveBy(
+ 100.milliseconds,
+ 1f,
+ 0f
+ )
+ pointers[2] =
+ pointers[2].moveBy(
+ 100.milliseconds,
+ -1f,
+ 0f
+ )
+
+ // Act
+ filter::onPointerInput.invokeOverAllPasses(*pointers)
+
+ // Assert
+ assertThat(log.filter { it.methodName == "onStart" }).isEmpty()
+ assertThat(log.filter { it.methodName == "onDrag" }).isEmpty()
+ }
+
+ @Test
+ fun onPointerInput_2Pointers1LockedInWrongOrientationOtherGoesUpThenItGoesUp_isCorrect() {
+
+ // Arrange
+
+ // Basic set up
+ filter.orientation = Orientation.Horizontal
+ dragStartBlocked = false
+ val scrollOrientationLocker = InternalScrollOrientationLocker()
+ filter::onCustomEvent.invokeOverAllPasses(
+ ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+ )
+
+ // One finger down
+ var time = 0.milliseconds
+ var pointer1 = down(0, time)
+ filter::onPointerInput.invokeOverAllPasses(pointer1)
+
+ // 2nd finger comes into play
+ time = 10.milliseconds
+ pointer1.moveTo(time)
+ var pointer2 = down(1, time)
+
+ // Lock the 2nd pointer to vertical
+ scrollOrientationLocker.attemptToLockPointers(listOf(pointer2), Orientation.Vertical)
+
+ // Dispatch 2nd finger down.
+ filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+ // Both pointers move a bunch.
+ repeat(11) {
+ time = 10.milliseconds
+ pointer1 = pointer1.moveBy(
+ 10.milliseconds,
+ 1f,
+ 0f
+ )
+ pointer2 = pointer2.moveBy(
+ 10.milliseconds,
+ 1f,
+ 0f
+ )
+ filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+ }
+
+ // Act 1
+
+ // Only Pointer 1 goes up
+ time = 10.milliseconds
+ pointer1 = pointer1.up(time)
+ pointer2 = pointer2.moveTo(time)
+ filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+ // Assert 1
+
+ // One pointer is still down, and even though it is locked in the other orientation, we
+ // still shouldn't stop yet.
+ assertThat(log.filter { it.methodName == "onStop" }).hasSize(0)
+
+ // Act 2
+
+ // 2nd is up
+ time = 10.milliseconds
+ pointer2 = pointer2.up(time)
+ filter::onPointerInput.invokeOverAllPasses(pointer2)
+
+ // This finger lifting should contribute no flinging since it was locked to a different
+ // orientation.
+ val loggedStops = log.filter { it.methodName == "onStop" }
+ assertThat(loggedStops).hasSize(1)
+ val velocity = loggedStops[0].pxPosition!!
+ assertThat(velocity.x).isEqualTo(0)
+ assertThat(velocity.y).isEqualTo(0)
+ }
+
+ @Test
+ fun onPointerInput_2Pointers1LockedInWrongOrientationItGoesUpThenOtherGoesUp_isCorrect() {
+
+ // Arrange
+
+ // Basic set up
+ filter.orientation = Orientation.Horizontal
+ dragStartBlocked = false
+ val scrollOrientationLocker = InternalScrollOrientationLocker()
+ filter::onCustomEvent.invokeOverAllPasses(
+ ShareScrollOrientationLockerEvent(scrollOrientationLocker)
+ )
+
+ var time = 0.milliseconds
+
+ // One finger down
+ var pointer1 = down(0, time)
+ filter::onPointerInput.invokeOverAllPasses(pointer1)
+
+ // 2nd finger comes into play
+ time += 10.milliseconds
+ pointer1.moveTo(time)
+ var pointer2 = down(1, time)
+
+ // Lock the 2nd pointer to vertical
+ scrollOrientationLocker.attemptToLockPointers(listOf(pointer2), Orientation.Vertical)
+
+ // Dispatch 2nd finger down.
+ filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+ // Both pointers move a bunch.
+ repeat(11) {
+ time += 10.milliseconds
+ pointer1 = pointer1.moveBy(
+ 10.milliseconds,
+ 1f,
+ 0f
+ )
+ pointer2 = pointer2.moveBy(
+ 10.milliseconds,
+ 1f,
+ 0f
+ )
+ filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+ }
+
+ // Act 1
+
+ // Only Pointer 2 goes up
+ time += 10.milliseconds
+ pointer1 = pointer1.moveBy(
+ 10.milliseconds,
+ 1f,
+ 0f
+ )
+ pointer2 = pointer2.up(time)
+ filter::onPointerInput.invokeOverAllPasses(pointer1, pointer2)
+
+ // Assert 1
+
+ // One pointer is still down, and even though it is locked in the other orientation, we
+ // still shouldn't stop yet.
+ assertThat(log.filter { it.methodName == "onStop" }).hasSize(0)
+
+ // Act 2
+
+ // 2nd is up
+ time += 10.milliseconds
+ pointer1 = pointer1.up(time)
+ filter::onPointerInput.invokeOverAllPasses(pointer1)
+
+ // This finger lifting should contribute no flinging since it was locked to a different
+ // orientation.
+ val loggedStops = log.filter { it.methodName == "onStop" }
+ assertThat(loggedStops).hasSize(1)
+ val velocity = loggedStops[0].pxPosition!!
+ assertThat(velocity.x).isWithin(.01f).of(100f)
+ assertThat(velocity.y).isWithin(.01f).of(0f)
+ }
+
// Tests that verify when onCancel should not be called.
@Test
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerSetupTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerSetupTest.kt
new file mode 100644
index 0000000..816dda2
--- /dev/null
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerSetupTest.kt
@@ -0,0 +1,491 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalPointerInput::class)
+
+package androidx.ui.core.gesture.scrollorientationlocking
+
+import androidx.ui.core.CustomEvent
+import androidx.ui.core.CustomEventDispatcher
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.gesture.ExperimentalPointerInput
+import androidx.ui.testutils.down
+import androidx.ui.testutils.moveTo
+import androidx.ui.testutils.up
+import androidx.ui.unit.milliseconds
+import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.argumentCaptor
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.never
+import com.nhaarman.mockitokotlin2.reset
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ScrollOrientationLockerSetupTest {
+
+ // Scenarios where dispatch does not happen.
+
+ // Valid CustomEvent, Down event, up event, all passes.
+ @Test
+ fun onPointerInput_validCustomEventThenDown_doesNotDispatchEvent() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+ scrollOrientationLocker.onCustomEventAllPasses(
+ ShareScrollOrientationLockerEvent(
+ InternalScrollOrientationLocker()
+ )
+ )
+
+ val down = down(0, 0.milliseconds)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+ verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+ }
+
+ // CustomEvent, Down then move, all passes.
+ @Test
+ fun onPointerInput_downThenMove_doesNotDispatchEvent() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val down = down(0, x = 0f, y = 0f)
+ val moveA = down.moveTo(1.milliseconds, 1f, 0f)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA))
+
+ // Assert
+ verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+ }
+
+ // CustomEvent, Down then up, all passes.
+ @Test
+ fun onPointerInput_downThenUp_doesNotDispatchEvent() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val down = down(0, x = 0f, y = 0f)
+ val up = down.up(1.milliseconds)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(up))
+
+ // Assert
+ verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+ }
+
+ // CustomEvent, Down then up, all passes.
+ @Test
+ fun onPointerInput_downThenCancel_doesNotDispatchEvent() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val down = down(0, x = 0f, y = 0f)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onCancel()
+
+ // Assert
+ verify(customEventDispatcher, never()).dispatchCustomEvent(any())
+ }
+
+ // Scenarios where dispatch does happen.
+
+ // Down event, all passes.
+ @Test
+ fun onPointerInput_downAllPasses_dispatchesNewInternalScrollOrientationLockerOnce() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down(0)))
+
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ verifyNoMoreInteractions(customEventDispatcher)
+ }
+
+ // Down event, InitialTunnel only.
+ @Test
+ fun onPointerInput_downInitialTunnel_dispatchesNewInternalScrollOrientationLockerOnce() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInput(listOf(down(0)), PointerEventPass.InitialDown)
+
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ verifyNoMoreInteractions(customEventDispatcher)
+ }
+
+ // Valid CustomEvent, Down event, up event, all passes.
+ @Test
+ fun onPointerInput_invalidCustomEventThenDown_dispatchesEvent() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+ scrollOrientationLocker.onCustomEventAllPasses(
+ object : CustomEvent {}
+ )
+
+ val down = down(0, 0.milliseconds)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down))
+
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ }
+
+ // Down event, followed by down event, all passes.
+ @Test
+ fun onPointerInput_downDown_dispatchesExistingScrollOrientationLockerOnce() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0, x = 0f, y = 0f)
+
+ val moveA = downA.moveTo(1.milliseconds, 0f, 0f)
+ val downB = down(1)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ var expected: InternalScrollOrientationLocker
+ argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ expected = this.firstValue.scrollOrientationLocker
+ }
+
+ reset(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA, downB))
+ var actual: InternalScrollOrientationLocker
+ argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ actual = this.firstValue.scrollOrientationLocker
+ }
+
+ assertThat(actual).isEqualTo(expected)
+ }
+
+ // Down event, followed by down event, InitialTunnel only.
+ @Test
+ fun onPointerInput_downDownInitialTunnel_dispatchesExistingScrollOrientationLockerOnce() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0, x = 0f, y = 0f)
+
+ val moveA = downA.moveTo(1.milliseconds, 0f, 0f)
+ val downB = down(1)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ var expected: InternalScrollOrientationLocker
+ argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ expected = this.firstValue.scrollOrientationLocker
+ }
+
+ reset(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInput(
+ listOf(moveA, downB),
+ PointerEventPass.InitialDown
+ )
+ var actual: InternalScrollOrientationLocker
+ argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ actual = this.firstValue.scrollOrientationLocker
+ }
+
+ assertThat(actual).isEqualTo(expected)
+ }
+
+ // Down then up then down, all passes.
+ @Test
+ fun onPointerInput_downThenUpThenDown_dispatchesEventDuringSecondDown() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0)
+ val upA = downA.up(1.milliseconds)
+ val downB = down(1)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(upA))
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+
+ // Assert
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ }
+
+ // Down then up then down, all passes: first internalLocker != last internalLocker
+ @Test
+ fun onPointerInput_downThenUpThenDown_firstInternalLockerNotEqualsFinalInternalLocker() {
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0, x = 0f, y = 0f)
+ val upA = downA.up(1.milliseconds)
+ val downB = down(1)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ val expected =
+ argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ this.firstValue.scrollOrientationLocker
+ }
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(upA))
+
+ reset(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+ val actual =
+ argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ this.firstValue.scrollOrientationLocker
+ }
+
+ assertThat(actual).isNotEqualTo(expected)
+ }
+
+ // Down then cancel then down, all passes.
+ @Test
+ fun onPointerInput_downThenCancelThenDown_dispatchesEventDuringSecondDown() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0)
+ val downB = down(1)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ scrollOrientationLocker.onCancel()
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+
+ // Assert
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ }
+
+ // Down then up then down, all passes: first internalLocker != last internalLocker
+ @Test
+ fun onPointerInput_downCancelThenDown_firstInternalLockerNotEqualsFinalInternalLocker() {
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0, x = 0f, y = 0f)
+ val downB = down(1)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ val expected =
+ argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ this.firstValue.scrollOrientationLocker
+ }
+
+ scrollOrientationLocker.onCancel()
+ reset(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+ val actual =
+ argumentCaptor<ShareScrollOrientationLockerEvent>().apply {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ this.firstValue.scrollOrientationLocker
+ }
+
+ assertThat(actual).isNotEqualTo(expected)
+ }
+
+ // Valid CustomEvent, Down then up then down, all passes.
+ @Test
+ fun onPointerInput_validCustomEventDownUpDown_dispatchesEvent() {
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+ scrollOrientationLocker.onCustomEventAllPasses(
+ ShareScrollOrientationLockerEvent(
+ InternalScrollOrientationLocker()
+ )
+ )
+
+ val downA = down(0, 0.milliseconds)
+ val upA = downA.up(1.milliseconds)
+ val downB = down(1, 2.milliseconds)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(upA))
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downB))
+
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ }
+
+ // CustomEvent, Down then move then down, all passes.
+ @Test
+ fun onPointerInput_downThenMoveThenDown_doesDispatchesEvent() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0, 0.milliseconds, x = 0f, y = 0f)
+
+ val moveA1 = downA.moveTo(1.milliseconds, 1f, 0f)
+
+ val moveA2 = moveA1.moveTo(2.milliseconds, 1f, 0f)
+ val downB = down(0, 2.milliseconds, x = 0f, y = 0f)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA1))
+
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA2, downB))
+
+ // Assert
+ verify(customEventDispatcher).dispatchCustomEvent(any())
+ }
+
+ // CustomEvent, Down then move then down, all passes.
+ @Test
+ fun onPointerInput_downThenMoveThenDown_firstInternalLockerMatchesSecondInternalLocker() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ val downA = down(0, 0.milliseconds, x = 0f, y = 0f)
+
+ val moveA1 = downA.moveTo(1.milliseconds, 1f, 0f)
+
+ val moveA2 = moveA1.moveTo(2.milliseconds, 1f, 0f)
+ val downB = down(0, 2.milliseconds, x = 0f, y = 0f)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(downA))
+ val expected =
+ argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ this.firstValue.scrollOrientationLocker
+ }
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA1))
+
+ reset(customEventDispatcher)
+
+ // Act
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(moveA2, downB))
+ val actual =
+ argumentCaptor<ShareScrollOrientationLockerEvent>().run {
+ verify(customEventDispatcher).dispatchCustomEvent(capture())
+ this.firstValue.scrollOrientationLocker
+ }
+
+ // Assert
+ assertThat(actual).isEqualTo(expected)
+ }
+
+ // Verification of situations when exceptions should be thrown.
+
+ @Test(expected = IllegalStateException::class)
+ fun attemptToLockPointers_notInitialized_illegalStateExceptionThrown() {
+ val customEventDispatcher = mock<CustomEventDispatcher>()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ scrollOrientationLocker.attemptToLockPointers(listOf(down(0)), Orientation.Vertical)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun getPointersFor_notInitialized_illegalStateExceptionThrown() {
+ val customEventDispatcher = mock<CustomEventDispatcher>()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ scrollOrientationLocker.getPointersFor(listOf(down(0)), Orientation.Vertical)
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun onCustomEvent_isLockerOWner_illegalStateExceptionThrown() {
+ val customEventDispatcher = mock<CustomEventDispatcher>()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+
+ scrollOrientationLocker.onPointerInputAllPasses(listOf(down(0)))
+
+ scrollOrientationLocker.onCustomEventAllPasses(
+ ShareScrollOrientationLockerEvent(
+ InternalScrollOrientationLocker()
+ )
+ )
+ }
+}
+
+private fun ScrollOrientationLocker.onPointerInputAllPasses(
+ changes: List<PointerInputChange>
+) {
+ PointerEventPass.values().forEach {
+ onPointerInputSetup(changes, it)
+ onPointerInputTearDown(changes, it)
+ }
+}
+
+private fun ScrollOrientationLocker.onPointerInput(
+ changes: List<PointerInputChange>,
+ pass: PointerEventPass
+) {
+ onPointerInputSetup(changes, pass)
+ onPointerInputTearDown(changes, pass)
+}
+
+private fun ScrollOrientationLocker.onCustomEventAllPasses(
+ event: CustomEvent
+) {
+ PointerEventPass.values().forEach {
+ onCustomEvent(event, it)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerTest.kt
new file mode 100644
index 0000000..8e304c9
--- /dev/null
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/gesture/scrollorientationlocking/ScrollOrientationLockerTest.kt
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalPointerInput::class)
+
+package androidx.ui.core.gesture.scrollorientationlocking
+
+import androidx.ui.core.CustomEventDispatcher
+import androidx.ui.core.PointerEventPass
+import androidx.ui.core.PointerInputChange
+import androidx.ui.core.gesture.ExperimentalPointerInput
+import androidx.ui.testutils.down
+import androidx.ui.unit.milliseconds
+import com.google.common.truth.Truth
+import com.nhaarman.mockitokotlin2.mock
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+val c1 = down(1, 0.milliseconds, x = 1f, y = 1f)
+val c2 = down(2, 0.milliseconds, x = 2f, y = 2f)
+
+class LockingConfig(
+ val changes: List<PointerInputChange>,
+ val orientation: Orientation
+)
+
+@RunWith(Parameterized::class)
+class ScrollOrientationLockerTest(
+ private val lockingConfigs: List<LockingConfig>,
+ private val inputChanges: List<PointerInputChange>,
+ private val inputOrientation: Orientation,
+ private val expectedOutput: List<PointerInputChange>
+) {
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(
+ name = "lockedConfigs = {0}, " +
+ "inputChanges = {1}, " +
+ "inputOrientation = {2}, " +
+ "expectedOutput = {3}"
+ )
+ fun parameters(): List<Array<Any?>> {
+
+ val configs = mutableListOf<Array<Any?>>()
+
+ val allPointerCombinations = listOf(
+ listOf(),
+ listOf(c1),
+ listOf(c2),
+ listOf(c1, c2)
+ )
+
+ val pointerCombinationsWith2 =
+ listOf(
+ listOf(c2),
+ listOf(c1, c2)
+ )
+
+ // If the requested orientation and the locked orientation is the same, whatever is
+ // requested is returned.
+ allPointerCombinations.forEach { locked ->
+ allPointerCombinations.forEach { input ->
+ Orientation.values().forEach { orientation ->
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(locked, orientation)
+ ),
+ input,
+ orientation,
+ input
+ )
+ )
+ }
+ }
+ }
+
+ // If pointer 1 is locked in orientation A, all requests with sets that include
+ // pointer 2 and in orientation B will result in the set that just includes pointer 2.
+ pointerCombinationsWith2.forEach { input ->
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1), Orientation.Horizontal)
+ ),
+ input,
+ Orientation.Vertical,
+ listOf(c2)
+ )
+ )
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1), Orientation.Vertical)
+ ),
+ input,
+ Orientation.Horizontal,
+ listOf(c2)
+ )
+ )
+ }
+
+ // If pointer 1 is locked in orientation A, and pointer 2 is locked in orientation B,
+ // all requests with sets that include pointer 2 and with orientation B will result in
+ // the set that just includes Pointer 2.
+ pointerCombinationsWith2.forEach { input ->
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1), Orientation.Horizontal),
+ LockingConfig(listOf(c2), Orientation.Vertical)
+ ),
+ input,
+ Orientation.Vertical,
+ listOf(c2)
+ )
+ )
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1), Orientation.Vertical),
+ LockingConfig(listOf(c2), Orientation.Horizontal)
+ ),
+ input,
+ Orientation.Horizontal,
+ listOf(c2)
+ )
+ )
+ }
+
+ // If all of the changes are locked to one orientation, no matter what is requested
+ // in the other, no changes will be returned.
+ allPointerCombinations.forEach { input ->
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1, c2), Orientation.Horizontal)
+ ),
+ input,
+ Orientation.Vertical,
+ listOf<PointerInputChange>()
+ )
+ )
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1, c2), Orientation.Vertical)
+ ),
+ input,
+ Orientation.Horizontal,
+ listOf<PointerInputChange>()
+ )
+ )
+ }
+
+ // If pointer 1 is locked in orientation A, and then is attempted to be locked in
+ // orientation B, all requests with sets that include pointer 2 and in orientation B
+ // will result in the set that just includes pointer 2.
+ pointerCombinationsWith2.forEach { input ->
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1), Orientation.Horizontal),
+ LockingConfig(listOf(c1), Orientation.Vertical)
+ ),
+ input,
+ Orientation.Vertical,
+ listOf(c2)
+ )
+ )
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1), Orientation.Vertical),
+ LockingConfig(listOf(c1), Orientation.Horizontal)
+ ),
+ input,
+ Orientation.Horizontal,
+ listOf(c2)
+ )
+ )
+ }
+
+ // If all of the changes are locked to orientation A, and then are attempted to be
+ // locked in brientation B , no matter what is requested in orientation B, no changes
+ // will be returned.
+ allPointerCombinations.forEach { input ->
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1, c2), Orientation.Horizontal),
+ LockingConfig(listOf(c1, c2), Orientation.Vertical)
+ ),
+ input,
+ Orientation.Vertical,
+ listOf<PointerInputChange>()
+ )
+ )
+ configs.add(
+ arrayOf(
+ listOf(
+ LockingConfig(listOf(c1, c2), Orientation.Vertical),
+ LockingConfig(listOf(c1, c2), Orientation.Horizontal)
+
+ ),
+ input,
+ Orientation.Horizontal,
+ listOf<PointerInputChange>()
+ )
+ )
+ }
+
+ return configs
+ }
+ }
+
+ @Test
+ fun test() {
+
+ // Arrange
+
+ val customEventDispatcher: CustomEventDispatcher = mock()
+ val scrollOrientationLocker = ScrollOrientationLocker(customEventDispatcher)
+ scrollOrientationLocker.onPointerInputSetup(inputChanges, PointerEventPass.InitialDown)
+ lockingConfigs.forEach {
+ scrollOrientationLocker.attemptToLockPointers(it.changes, it.orientation)
+ }
+
+ // Act
+ val actual = scrollOrientationLocker.getPointersFor(inputChanges, inputOrientation)
+
+ // Assert
+ Truth.assertThat(expectedOutput).isEqualTo(actual)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt
index 57c608b..a019b63 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerDragTest.kt
@@ -17,6 +17,7 @@
package androidx.ui.core.selection
import androidx.compose.frames.commit
+import androidx.compose.frames.inFrame
import androidx.compose.frames.open
import androidx.test.filters.SmallTest
import androidx.ui.core.LayoutCoordinates
@@ -82,7 +83,7 @@
@Before
fun setup() {
- open(false) // we open a Frame so state reads are allowed
+ if (!inFrame) open(false) // we open a Frame so state reads are allowed
selectionRegistrar.subscribe(selectable)
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
index 6fc39b6..a3bd118 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerLongPressDragTest.kt
@@ -17,6 +17,7 @@
package androidx.ui.core.selection
import androidx.compose.frames.commit
+import androidx.compose.frames.inFrame
import androidx.compose.frames.open
import androidx.test.filters.SmallTest
import androidx.ui.core.LayoutCoordinates
@@ -79,7 +80,7 @@
@Before
fun setup() {
- open(false) // we open a Frame so state reads are allowed
+ if (!inFrame) open(false) // we open a Frame so state reads are allowed
val containerLayoutCoordinates = mock<LayoutCoordinates> {
on { isAttached } doReturn true
}
diff --git a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt
index b6888ed..10d0605 100644
--- a/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt
+++ b/ui/ui-core/src/test/kotlin/androidx/ui/core/selection/SelectionManagerTest.kt
@@ -17,6 +17,7 @@
package androidx.ui.core.selection
import androidx.compose.frames.commit
+import androidx.compose.frames.inFrame
import androidx.compose.frames.open
import androidx.test.filters.SmallTest
import androidx.ui.core.LayoutCoordinates
@@ -83,7 +84,7 @@
@Before
fun setup() {
- open(false) // we open a Frame so state reads are allowed
+ if (!inFrame) open(false) // we open a Frame so state reads are allowed
selectionRegistrar.subscribe(selectable)
selectionManager.containerLayoutCoordinates = containerLayoutCoordinates
selectionManager.hapticFeedBack = hapticFeedback
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt
index 05917ff..cb4e62ad 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Matrix.kt
@@ -18,4 +18,10 @@
class Matrix() {
fun isIdentity() = true
+
+ fun reset() {
+ }
+
+ fun setTranslate(dx: Float, dy: Float) {
+ }
}
\ No newline at end of file
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
index 42216bb..9a22979 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/graphics/Path.kt
@@ -53,4 +53,10 @@
}
fun isConvex(): Boolean = skijaPath.isConvex
-}
\ No newline at end of file
+ fun addPath(src: Path, dx: Float, dy: Float) {
+ skijaPath.addPath(src.skijaPath, dx, dy)
+ }
+
+ fun transform(matrix: Matrix) {
+ }
+}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt
index 25a05ac..a9d9b12 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/os/Handler.kt
@@ -19,6 +19,7 @@
import javax.swing.SwingUtilities
public class Handler() {
+ constructor(looper: Looper) : this()
constructor(looper: Looper, callback: Handler.Callback) : this()
constructor(looper: Looper, callback: Callback, async: Boolean) : this()
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
index 1b530d4..2b8e02b 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/View.kt
@@ -79,8 +79,6 @@
open fun onLayout (changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {}
- open fun onAttachedToWindow() {}
-
open fun dispatchDraw(canvas: Canvas) {}
open fun dispatchTouchEvent(event: MotionEvent): Boolean = true
@@ -148,6 +146,10 @@
var mRecreateDisplayList: Boolean = false
+ var isAttachedToWindow = false
+
+ var isLayoutRequested = false
+
fun layout(left: Int, top: Int, right: Int, bottom: Int) {
this.left = left
this.top = top
@@ -181,4 +183,8 @@
bottom += offset
}
}
+
+ open fun onAttachedToWindow() {
+ isAttachedToWindow = true
+ }
}
diff --git a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
index 585f962..7d30c7d 100644
--- a/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
+++ b/ui/ui-desktop/android-emu/src/desktopMain/kotlin/android/view/ViewGroup.kt
@@ -26,7 +26,8 @@
abstract class ViewGroup(context: Context) : View(context), ViewParent {
var clipChildren: Boolean = true
var children = mutableListOf<View>()
- val childCount = children.count()
+ val childCount: Int
+ get() = children.count()
fun getChildAt(i: Int) = children[i]
@@ -48,6 +49,13 @@
children.add(child)
}
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ children.forEach {
+ it.onAttachedToWindow()
+ }
+ }
+
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
fun drawChild(canvas: Canvas, view: View, drawingTime: Long): Boolean {
diff --git a/ui/ui-desktop/build.gradle b/ui/ui-desktop/build.gradle
index 2d31f7d..05ecc18 100644
--- a/ui/ui-desktop/build.gradle
+++ b/ui/ui-desktop/build.gradle
@@ -51,7 +51,7 @@
repositories {
// To allow using local Skija build.
- mavenLocal()
+ // mavenLocal()
}
configurations {
@@ -84,14 +84,10 @@
ui_components "org.jogamp.gluegen:gluegen-rt-natives-macosx-universal:2.4.0-rc-20200306"
compose_compiler_jar project(":compose:compose-compiler")
-}
-dependencies {
kotlinPlugin project(path: ":compose:compose-compiler")
}
-def joglDir = "${project.rootDir}/ui-desktop/libs"
-def androidxDir = "${project.rootDir}/ui-desktop/libs"
def composeClassDir = project.rootDir.absolutePath + "/ui-desktop/compose-libs/"
kotlin {
@@ -100,9 +96,8 @@
sourceSets {
commonMain.dependencies {
api(KOTLIN_STDLIB_COMMON)
- implementation project(":compose:compose-runtime")
+ api project(":compose:compose-runtime")
}
-
jvmMain {
resources.srcDirs += new File(SupportConfigKt.getExternalProjectPath(project), "noto-fonts/other/")
@@ -110,30 +105,28 @@
jvmMain.dependencies {
api(KOTLIN_STDLIB)
+ api(KOTLIN_STDLIB_JDK8)
api(KOTLIN_COROUTINES_CORE)
api "org.jetbrains.skija:skija:0.2.41"
api project(":ui:ui-desktop:android-emu")
- api files("$joglDir/gluegen-rt.jar")
- api files("$joglDir/jogl-all.jar")
-
- api fileTree(project.rootDir.absolutePath + "/ui-desktop/compose-libs")
+ api fileTree(composeClassDir)
implementation(KOTLIN_COROUTINES_SWING)
- implementation files("$androidxDir/core-common-2.1.0.jar")
implementation "androidx.lifecycle:lifecycle-common:2.3.0-alpha01"
implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
- implementation files("$joglDir/gluegen-rt-natives-macosx-universal.jar")
- implementation files("$joglDir/jogl-all-natives-macosx-universal.jar")
-
// TODO: this is a bit ugly. We introduce dependency here, but in fact
// manually copy it later, as run task will have .aar in the classpath.
implementation "androidx.core:core:1.0.0"
implementation "androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01"
}
+
+ jvmTest.dependencies {
+ implementation(JUNIT)
+ }
}
}
@@ -200,7 +193,6 @@
fis.close()
}
-
// Find in dependencies first (BFS) task's output ending with `name`.
String findInDeps(Task root, Closure<Boolean> matcher) {
// Do BFS by deps.
@@ -241,7 +233,60 @@
fs.close()
}
-task extractJars {
+project.tasks.register("extractJars").configure {
+ inputs.files(project.provider {
+ def result = []
+ uiComponents.each { component ->
+ def depProject = project(":ui:" + component)
+ def task = depProject.tasks.named("assemble").get()
+ def srcJar = findInDeps(task, { absolutePath ->
+ absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+ })
+ result.add(file(srcJar))
+ }
+ configurations.ui_components.getIncoming().artifactView(
+ { config ->
+ config.attributes({container ->
+ // ... container.attribute(Attribute.of("artifactType", String.class), "android-classes")
+ })
+ })
+ .getArtifacts().getArtifactFiles().each { component ->
+ result.add(component)
+ }
+ def runtimeProject = project(":compose:compose-runtime")
+ def runtimeJar = findInDeps(runtimeProject.tasks.named("assemble").get(), {
+ absolutePath ->
+ Pattern.matches(".*/compose-runtime-desktop.*.jar", absolutePath)
+ })
+ if (runtimeJar == null)
+ throw new Error("cannot find compose-runtime.jar")
+ result.add(file(runtimeJar))
+
+ return result
+ })
+
+ outputs.files(project.provider {
+ def result = [fileTree(dir: composeClassDir, include: [])]
+ uiComponents.each { component ->
+ def depProject = project(":ui:" + component)
+ def task = depProject.tasks.named("assemble").get()
+ def srcJar = findInDeps(task, { absolutePath ->
+ absolutePath.endsWith("classes.jar") && absolutePath.contains(component)
+ })
+ result.add(file(composeClassDir + component + ".jar"))
+ }
+ configurations.ui_components.getIncoming().artifactView(
+ { config ->
+ config.attributes({container ->
+ // ... container.attribute(Attribute.of("artifactType", String.class), "android-classes")
+ })
+ })
+ .getArtifacts().getArtifactFiles().each { component ->
+ result.add(file(composeClassDir + component.name))
+ }
+ return result
+ })
+
doLast {
// Find all JAR files matching components.
file(composeClassDir).mkdir()
@@ -258,24 +303,6 @@
makeLinkOrCopy(srcJar, destJar)
}
}
- // Compose compiler plugin build does ugly renaming tricks, so find the proper jar.
- def compilerProject = project(":compose:compose-compiler")
- def compilerJar = findInDeps(compilerProject.tasks.named("embeddedPlugin").get(), {
- absolutePath ->
- println(absolutePath)
- Pattern.matches(".*/jarjar/compose-compiler.jar", absolutePath)
- })
- if (compilerJar == null)
- throw new Error("cannot find compose-compiler.jar")
- makeLinkOrCopy(compilerJar, composeClassDir + "compose-compiler.jar")
- def runtimeProject = project(":compose:compose-runtime")
- def runtimeJar = findInDeps(runtimeProject.tasks.named("assemble").get(), {
- absolutePath ->
- Pattern.matches(".*/compose-runtime-desktop.*.jar", absolutePath)
- })
- if (runtimeJar == null)
- throw new Error("cannot find compose-runtime.jar")
- makeLinkOrCopy(runtimeJar, composeClassDir + "compose-runtime.jar")
configurations.ui_components.getIncoming().artifactView(
{ config ->
@@ -304,13 +331,25 @@
useIR = true
}
}
-
-task desktopJar(type: Jar) {
+project.tasks.register("jar", Jar).configure {
baseName = "ui-desktop"
from { kotlin.jvm().compilations["main"].output.allOutputs }
destinationDir file(composeClassDir)
}
+project.tasks.register("test", JavaExec).configure {
+ dependsOn(":ui:ui-desktop:jar")
+ main = 'androidx.ui.desktop.RunnerKt'
+ def compilation = kotlin.jvm().compilations["test"]
+ classpath =
+ compilation.output.allOutputs +
+ compilation.runtimeDependencyFiles +
+ fileTree(composeClassDir)
+}
+
clean.doFirst {
delete composeClassDir
-}
\ No newline at end of file
+}
+
+// TODO(igotti): figure out buildbots breakage.
+// rootProject.tasks.getByName("buildOnServer").dependsOn(project.path + ":jar")
\ No newline at end of file
diff --git a/ui/ui-desktop/samples/build.gradle b/ui/ui-desktop/samples/build.gradle
index 675bf8d..becec20 100644
--- a/ui/ui-desktop/samples/build.gradle
+++ b/ui/ui-desktop/samples/build.gradle
@@ -35,7 +35,7 @@
jvmMain {
resources.srcDirs += "src/jvmMain/res"
}
-
+
jvmMain.dependencies {
implementation project(":ui:ui-desktop")
implementation fileTree(sdkDir)
@@ -50,7 +50,7 @@
}
task run1(type: JavaExec) {
- dependsOn(":ui:ui-desktop:desktopJar")
+ dependsOn(":ui:ui-desktop:jar")
main = 'androidx.ui.desktop.examples.example1.MainKt'
def compilation = kotlin.jvm().compilations["main"]
classpath =
@@ -60,7 +60,7 @@
}
task run2(type: JavaExec) {
- dependsOn(":ui:ui-desktop:desktopJar")
+ dependsOn(":ui:ui-desktop:jar")
main = 'androidx.ui.desktop.examples.example2.MainKt'
def compilation = kotlin.jvm().compilations["main"]
classpath =
diff --git a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
index 8e8a28e..d9eb5cf 100644
--- a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
+++ b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example1/Main.kt
@@ -17,21 +17,23 @@
import android.graphics.Bitmap
import androidx.compose.Composable
+import androidx.compose.remember
import androidx.compose.state
import androidx.compose.remember
import androidx.ui.core.Alignment
import androidx.ui.core.Modifier
-import androidx.ui.graphics.Color
+import androidx.ui.desktop.examples.mainWith
import androidx.ui.foundation.Image
import androidx.ui.foundation.Text
import androidx.ui.foundation.drawBackground
-import androidx.ui.graphics.asImageAsset
+import androidx.ui.graphics.Color
import androidx.ui.graphics.ImageAsset
+import androidx.ui.graphics.asImageAsset
import androidx.ui.layout.Arrangement
import androidx.ui.layout.Column
import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.wrapContentSize
import androidx.ui.layout.preferredHeight
+import androidx.ui.layout.wrapContentSize
import androidx.ui.material.Button
import androidx.ui.material.CircularProgressIndicator
import androidx.ui.material.ExtendedFloatingActionButton
@@ -39,12 +41,18 @@
import androidx.ui.material.Scaffold
import androidx.ui.material.Slider
import androidx.ui.material.TopAppBar
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.SpanStyle
import androidx.ui.unit.dp
-
-import androidx.ui.desktop.examples.mainWith
+import androidx.ui.unit.sp
+import androidx.ui.text.font.fontFamily
+import androidx.ui.desktop.font
+import androidx.ui.layout.padding
private const val title = "Desktop Compose Elements"
+val italicFont = fontFamily(font("Noto Italic", "NotoSans-Italic.ttf"))
+
fun main() = mainWith(title) @Composable {
Scaffold(
topBar = {
@@ -72,6 +80,46 @@
.preferredHeight(56.dp)
.wrapContentSize(Alignment.Center)
)
+
+ Text(
+ text = with(AnnotatedString.Builder("The quick ")) {
+ pushStyle(SpanStyle(color = Color(0xff964B00)))
+ append("brown fox")
+ pop()
+ append(" 🦊 ate a ")
+ pushStyle(SpanStyle(fontSize = 30.sp))
+ append("zesty hamburgerfons")
+ pop()
+ append(" 🍔.\nThe 👩👩👧👧 laughed.")
+ addStyle(SpanStyle(color = Color.Green), 25, 35)
+ toAnnotatedString()
+ },
+ color = Color.Black
+ )
+
+ Text(
+ text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do" +
+ " eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad" +
+ " minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip" +
+ " ex ea commodo consequat. Duis aute irure dolor in reprehenderit in" +
+ " voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur" +
+ " sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt" +
+ " mollit anim id est laborum."
+ )
+
+ Text(
+ text = "fun <T : Comparable<T>> List<T>.quickSort(): List<T> = when {\n" +
+ " size < 2 -> this\n" +
+ " else -> {\n" +
+ " val pivot = first()\n" +
+ " val (smaller, greater) = drop(1).partition { it <= pivot }\n" +
+ " smaller.quickSort() + pivot + greater.quickSort()\n" +
+ " }\n" +
+ "}",
+ modifier = Modifier.padding(10.dp),
+ fontFamily = italicFont
+ )
+
Button(onClick = {
amount.value++
}) {
diff --git a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt
index 64b13cd..7d2298a 100644
--- a/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt
+++ b/ui/ui-desktop/samples/src/jvmMain/kotlin/androidx/ui/desktop/examples/example2/Main.kt
@@ -20,7 +20,6 @@
import androidx.ui.foundation.Canvas
import androidx.ui.geometry.Offset
import androidx.ui.graphics.Color
-import androidx.ui.graphics.drawscope.Stroke
import androidx.ui.graphics.drawscope.inset
import androidx.ui.graphics.drawscope.rotate
import androidx.ui.graphics.drawscope.withTransform
@@ -37,9 +36,9 @@
drawRect(Color.Magenta)
inset(10.0f) {
drawLine(
- p1 = Offset.Zero,
- p2 = Offset(size.width, size.height),
- stroke = Stroke(width = 5.0f),
+ start = Offset.Zero,
+ end = Offset(size.width, size.height),
+ strokeWidth = 5.0f,
color = Color.Red
)
}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopFont.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopFont.kt
new file mode 100644
index 0000000..ef68021a
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopFont.kt
@@ -0,0 +1,98 @@
+/*
+* Copyright 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package androidx.ui.desktop
+
+import org.jetbrains.skija.SkTypeface
+import androidx.ui.text.font.Font as uiFont
+import androidx.ui.text.font.FontWeight
+import androidx.ui.text.font.FontStyle
+import androidx.ui.text.font.FontFamily
+import androidx.ui.text.font.FontListFontFamily
+import org.jetbrains.skija.FontCollection
+import org.jetbrains.skija.FontManager
+import org.jetbrains.skija.TypefaceFontProvider
+import java.nio.file.Files
+import java.nio.file.StandardCopyOption
+import java.io.File
+
+data class Font(
+ val alias: String,
+ val path: String,
+ override val weight: FontWeight = FontWeight.Normal,
+ override val style: FontStyle = FontStyle.Normal
+) : uiFont
+
+fun font(
+ alias: String,
+ path: String,
+ weight: FontWeight = FontWeight.Normal,
+ style: FontStyle = FontStyle.Normal
+): Font = Font(alias, path, weight, style)
+
+class FontLoader() : uiFont.ResourceLoader {
+ val fonts = FontCollection()
+ private val fontProvider = TypefaceFontProvider()
+
+ init {
+ fonts.setDefaultFontManager(FontManager.getDefault())
+ fonts.setAssetFontManager(fontProvider)
+ }
+
+ fun ensureRegistered(fontFamily: FontFamily): List<String> =
+ when (fontFamily) {
+ is FontListFontFamily -> fontFamily.fonts.map { load(it) }
+ FontFamily.Default -> listOf()
+ else -> throw IllegalArgumentException("Unknown font family type: $fontFamily")
+ }
+
+ private val registered = mutableSetOf<String>()
+ override fun load(font: uiFont): String {
+ when (font) {
+ is Font -> {
+ synchronized(this) {
+ if (!registered.contains(font.alias)) {
+ val typeface = typefaceResource(font.path)
+ fontProvider.registerTypeface(typeface, font.alias)
+ registered.add(font.alias)
+ }
+ }
+ return font.alias
+ }
+ else -> throw IllegalArgumentException("Unknown font type: $font")
+ }
+ }
+}
+
+// TODO: get fontFamily from loaded typeface via SkTypeface.getFamilyName
+private fun typefaceResource(resourcePath: String): SkTypeface {
+ val path = getFontPathAsString(resourcePath)
+ return SkTypeface.makeFromFile(path, 0)
+}
+
+// TODO: add to skija an ability to load typefaces from memory
+fun getFontPathAsString(resourcePath: String): String {
+ val tempDir = File(System.getProperty("java.io.tmpdir"), "compose").apply {
+ mkdirs()
+ deleteOnExit()
+ }
+ val tempFile = File(tempDir, resourcePath).apply {
+ deleteOnExit()
+ }
+ val stream = Thread.currentThread().contextClassLoader.getResourceAsStream(resourcePath)
+ if (stream == null) throw Error("Cannot find font $resourcePath")
+ Files.copy(stream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
+ return tempFile.absolutePath
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraph.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraph.kt
new file mode 100644
index 0000000..610b4ac
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraph.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.ui.desktop
+
+import androidx.ui.geometry.Rect
+import androidx.ui.graphics.Canvas
+import androidx.ui.graphics.Path
+import androidx.ui.graphics.AndroidPath
+import androidx.ui.text.Paragraph
+import androidx.ui.text.ParagraphConstraints
+import androidx.ui.text.ParagraphIntrinsics
+import androidx.ui.text.TextRange
+import androidx.ui.text.style.TextDirection
+import androidx.ui.geometry.Offset
+import org.jetbrains.skija.Paragraph as SkParagraph
+
+internal class DesktopParagraph(
+ intrinsics: ParagraphIntrinsics,
+ val maxLines: Int,
+ val ellipsis: Boolean,
+ val constraints: ParagraphConstraints
+) : Paragraph {
+
+ val paragraphIntrinsics = intrinsics as DesktopParagraphIntrinsics
+
+ val para = paragraphIntrinsics.para
+
+ init {
+ para.layout(constraints.width)
+ }
+
+ override val width: Float
+ get() = para.getMaxWidth()
+
+ override val height: Float
+ get() = para.getHeight()
+
+ override val minIntrinsicWidth: Float
+ get() = paragraphIntrinsics.minIntrinsicWidth
+
+ override val maxIntrinsicWidth: Float
+ get() = paragraphIntrinsics.maxIntrinsicWidth
+
+ override val firstBaseline: Float
+ get() = para.getLineMetrics().first().baseline.toFloat()
+
+ override val lastBaseline: Float
+ get() = para.getLineMetrics().last().baseline.toFloat()
+
+ override val didExceedMaxLines: Boolean
+ // TODO: support text ellipsize.
+ get() = para.lineNumber() < maxLines
+
+ override val lineCount: Int
+ get() = para.lineNumber().toInt()
+
+ override val placeholderRects: List<Rect?> get() {
+ println("Paragraph.placeholderRects")
+ return listOf()
+ }
+
+ override fun getPathForRange(start: Int, end: Int): Path {
+ val boxes = para.getRectsForRange(
+ start,
+ end,
+ SkParagraph.RectHeightStyle.MAX,
+ SkParagraph.RectWidthStyle.MAX
+ )
+ val path = Path() as AndroidPath
+ for (b in boxes) {
+ path.internalPath.skijaPath.addRect(b.rect)
+ }
+ return path
+ }
+
+ override fun getCursorRect(offset: Int): Rect {
+ println("Paragraph.getCursorRect $offset")
+ return Rect(0.0f, 0.0f, 0.0f, 0.0f)
+ }
+
+ override fun getLineLeft(lineIndex: Int): Float {
+ println("Paragraph.getLineLeft $lineIndex")
+ return 0.0f
+ }
+
+ override fun getLineRight(lineIndex: Int): Float {
+ println("Paragraph.getLineRight $lineIndex")
+ return 0.0f
+ }
+
+ override fun getLineTop(lineIndex: Int): Float {
+ println("Paragraph.getLineTop $lineIndex")
+ return 0.0f
+ }
+
+ override fun getLineBottom(lineIndex: Int): Float {
+ println("Paragraph.getLineBottom $lineIndex")
+ return 0.0f
+ }
+
+ override fun getLineHeight(lineIndex: Int): Float {
+ println("Paragraph.getLineHeight $lineIndex")
+ return 0.0f
+ }
+
+ override fun getLineWidth(lineIndex: Int): Float {
+ println("Paragraph.getLineWidth $lineIndex")
+ return 0.0f
+ }
+
+ override fun getLineStart(lineIndex: Int): Int {
+ println("Paragraph.getLineStart $lineIndex")
+ return 0
+ }
+
+ override fun getLineEnd(lineIndex: Int): Int {
+ println("Paragraph.getLineEnd $lineIndex")
+ return 0
+ }
+
+ override fun getLineEllipsisOffset(lineIndex: Int): Int {
+ println("Paragraph.getLineEllipsisOffset $lineIndex")
+ return 0
+ }
+
+ override fun getLineEllipsisCount(lineIndex: Int): Int {
+ println("Paragraph.getLineEllipsisCount $lineIndex")
+ return 0
+ }
+
+ override fun getLineForOffset(offset: Int): Int {
+ println("Paragraph.getLineForOffset $offset")
+ return 0
+ }
+
+ override fun getHorizontalPosition(offset: Int, usePrimaryDirection: Boolean): Float {
+ println("getHorizontalPosition $offset, $usePrimaryDirection")
+ return 0.0f
+ }
+
+ override fun getParagraphDirection(offset: Int): TextDirection = TextDirection.Ltr
+
+ override fun getBidiRunDirection(offset: Int): TextDirection = TextDirection.Ltr
+
+ override fun getOffsetForPosition(position: Offset): Int {
+ return para.getGlyphPositionAtCoordinate(position.x, position.y).position
+ }
+
+ override fun getBoundingBox(offset: Int): Rect {
+ println("getBoundingBox $offset")
+ return Rect(0.0f, 0.0f, 0.0f, 0.0f)
+ }
+
+ override fun getWordBoundary(offset: Int): TextRange {
+ println("getWordBoundary $offset")
+ return TextRange(0, 0)
+ }
+
+ override fun paint(canvas: Canvas) {
+ para.paint(canvas.nativeCanvas.skijaCanvas, 0.0f, 0.0f)
+ }
+}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraphIntrinsics.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraphIntrinsics.kt
new file mode 100644
index 0000000..2354d0d
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopParagraphIntrinsics.kt
@@ -0,0 +1,159 @@
+/*
+* Copyright 2020 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package androidx.ui.desktop
+
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.toArgb
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.ParagraphIntrinsics
+import androidx.ui.text.Placeholder
+import androidx.ui.text.SpanStyle
+import androidx.ui.text.SpanStyleRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.font.Font
+import androidx.ui.unit.Density
+import androidx.ui.unit.TextUnit
+import kotlin.math.ceil
+import org.jetbrains.skija.Paragraph
+import org.jetbrains.skija.ParagraphBuilder
+import org.jetbrains.skija.ParagraphStyle
+import org.jetbrains.skija.TextStyle as SkTextStyle
+
+internal class DesktopParagraphIntrinsics(
+ val text: String,
+ style: TextStyle,
+ spanStyles: List<SpanStyleRange>,
+ @Suppress("UNUSED_PARAMETER") placeholders: List<AnnotatedString.Range<Placeholder>>,
+ @Suppress("UNUSED_PARAMETER") density: Density,
+ resourceLoader: Font.ResourceLoader
+) : ParagraphIntrinsics {
+
+ val fontLoader = resourceLoader as FontLoader
+ val para: Paragraph
+ init {
+ para = buildParagraph(text, style, spanStyles)
+
+ para.layout(Float.POSITIVE_INFINITY)
+ }
+
+ override val minIntrinsicWidth = ceil(para.getMinIntrinsicWidth())
+ override val maxIntrinsicWidth = ceil(para.getMaxIntrinsicWidth())
+
+ /**
+ * SkParagraph styles model doesn't match Compose's one.
+ * SkParagraph has only a stack-based push/pop styles interface that works great with Span
+ * trees.
+ * But in Compose we have a list of SpanStyles attached to arbitrary ranges, possibly
+ * overlapped, where a position in the list denotes style's priority
+ * We map Compose styles to SkParagraph styles by projecting every range start/end to single
+ * positions line and maintaining a list of active styles while building a paragraph. This list
+ * of active styles is being compiled into single SkParagraph's style for every chunk of text
+ */
+ private fun buildParagraph(
+ text: String,
+ textStyle: TextStyle,
+ spanStyles: List<SpanStyleRange>
+ ): Paragraph {
+ val cuts = spansToCuts(spanStyles)
+
+ var pos = 0
+ val ps = textStyleToParagraphStyle(textStyle)
+ val pb = ParagraphBuilder(ps, fontLoader.fonts)
+ // TODO: for some reasons paragraph style doesn't apply to text. maybe it's Skia bug,
+ // we need to investigate
+ val currentStyles = mutableListOf(Pair(0, textStyle.toSpanStyle()))
+ pb.pushStyle(textStylesToSkStyle(currentStyles)!!)
+
+ for (cut in cuts) {
+ pb.addText(text.subSequence(pos, cut.position).toString())
+ pb.popStyle()
+
+ when (cut.instruction) {
+ StyleInstruction.ADD -> currentStyles.add(Pair(cut.priority, cut.style))
+ StyleInstruction.REMOVE -> currentStyles.remove(Pair(cut.priority, cut.style))
+ }
+
+ textStylesToSkStyle(currentStyles)?.let { ts ->
+ pb.pushStyle(ts)
+ }
+ pos = cut.position
+ }
+
+ pb.addText(text.subSequence(pos, text.length).toString())
+
+ return pb.build()
+ }
+
+ private enum class StyleInstruction {
+ ADD,
+ REMOVE
+ }
+
+ private data class Cut(
+ val position: Int,
+ val priority: Int,
+ val style: SpanStyle,
+ val instruction: StyleInstruction
+ )
+
+ private fun spansToCuts(spans: List<SpanStyleRange>): List<Cut> {
+ val positions = mutableMapOf<Int, Cut>()
+ for ((i, span) in spans.withIndex()) {
+ positions[span.start] = Cut(span.start, i, span.item, StyleInstruction.ADD)
+ positions[span.end] = Cut(span.end, i, span.item, StyleInstruction.REMOVE)
+ }
+
+ val cuts = ArrayList<Cut>(positions.size)
+
+ for (v in positions.toSortedMap().values) {
+ cuts.add(v)
+ }
+ return cuts
+ }
+
+ private fun textStyleToParagraphStyle(style: TextStyle): ParagraphStyle {
+ val pStyle = ParagraphStyle()
+ val textStyle = SkTextStyle()
+ applyStyles(style.toSpanStyle(), textStyle)
+ pStyle.setTextStyle(textStyle)
+ return pStyle
+ }
+
+ private fun applyStyles(from: SpanStyle, to: SkTextStyle) {
+ if (from.color != Color.Unset) {
+ to.setColor(from.color.toArgb())
+ }
+ from.fontFamily?.let {
+ val fontFamilies = fontLoader.ensureRegistered(it)
+ to.setFontFamilies(fontFamilies.toTypedArray())
+ }
+ // TODO: support [TextUnit.Em]
+ if (from.fontSize != TextUnit.Inherit) {
+ to.setFontSize(from.fontSize.value)
+ }
+ }
+
+ private fun textStylesToSkStyle(styles: List<Pair<Int, SpanStyle>>): SkTextStyle? {
+ if (styles.isEmpty()) {
+ return null
+ }
+ val skStyle = SkTextStyle()
+ for (s in styles.sortedBy { (priority, _) -> priority }.map { (_, v) -> v }) {
+ applyStyles(s, skStyle)
+ }
+ return skStyle
+ }
+}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelection.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelection.kt
new file mode 100644
index 0000000..2902926
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelection.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.ui.desktop
+
+import androidx.ui.core.Modifier
+import androidx.ui.core.Layout
+import androidx.ui.core.gesture.DragObserver
+import androidx.compose.Composable
+import androidx.ui.core.onPositioned
+import androidx.ui.geometry.Offset
+import kotlin.math.max
+import androidx.compose.remember
+import androidx.compose.state
+import androidx.ui.core.selection.Selection
+import androidx.ui.core.selection.SelectionRegistrarAmbient
+import androidx.compose.Providers
+import androidx.ui.core.pointerinput.PointerInputModifier
+import androidx.ui.core.pointerinput.PointerInputFilter
+import androidx.ui.core.composed
+import androidx.ui.core.gesture.rawDragGestureFilter
+import androidx.ui.core.gesture.rawPressStartGestureFilter
+
+@Composable
+private fun Wrap(modifier: Modifier = Modifier, children: @Composable () -> Unit) {
+ Layout(modifier = modifier, children = children) { measurables, constraints, _ ->
+ val placeables = measurables.map { measurable ->
+ measurable.measure(constraints)
+ }
+
+ val width = placeables.fold(0) { maxWidth, placeable ->
+ max(maxWidth, (placeable.width))
+ }
+
+ val height = placeables.fold(0) { minWidth, placeable ->
+ max(minWidth, (placeable.height))
+ }
+
+ layout(width, height) {
+ placeables.forEach { placeable ->
+ placeable.placeAbsolute(0, 0)
+ }
+ }
+ }
+}
+
+@Composable
+internal fun DesktopSelectionContainer(children: @Composable () -> Unit) {
+ val selection = state<Selection?> { null }
+ DesktopSelectionContainer(
+ selection = selection.value,
+ onSelectionChange = { selection.value = it },
+ children = children
+ )
+}
+
+private class PointerInputModifierImpl(override val pointerInputFilter: PointerInputFilter) :
+ PointerInputModifier
+
+private fun Modifier.selectionFilter(observer: DragObserver): Modifier = composed {
+ val glue = remember { DragGlue(observer) }
+ rawDragGestureFilter(glue, glue::started)
+ .rawPressStartGestureFilter(glue::startDrag, true)
+}
+
+private class DragGlue(val observer: DragObserver) : DragObserver by observer {
+ var started = false
+
+ fun startDrag(downPosition: Offset) {
+ started = true
+ observer.onStart(downPosition)
+ }
+
+ override fun onStop(velocity: Offset) {
+ started = false
+ observer.onStop(velocity)
+ }
+
+ override fun onCancel() {
+ started = false
+ observer.onCancel()
+ }
+}
+
+@Composable
+fun DesktopSelectionContainer(
+ selection: Selection?,
+ onSelectionChange: (Selection?) -> Unit,
+ children: @Composable () -> Unit
+) {
+ val registrarImpl = remember { DesktopSelectionRegistrar() }
+ val manager = remember { DesktopSelectionManager(registrarImpl) }
+
+ manager.onSelectionChange = onSelectionChange
+ manager.selection = selection
+
+ val gestureModifiers =
+ Modifier.selectionFilter(manager.observer)
+
+ val modifier = remember {
+ gestureModifiers.onPositioned {
+ manager.containerLayoutCoordinates = it
+ }
+ }
+
+ Providers(SelectionRegistrarAmbient provides registrarImpl) {
+ Wrap(modifier) {
+ children()
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionManager.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionManager.kt
new file mode 100644
index 0000000..9682623
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionManager.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.desktop
+
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.ui.core.LayoutCoordinates
+import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.gesture.DragObserver
+import androidx.ui.geometry.Offset
+import androidx.ui.core.selection.Selection
+import androidx.ui.core.selection.Selectable
+
+internal class DesktopSelectionManager(private val selectionRegistrar: DesktopSelectionRegistrar) {
+ private var dragBeginPosition = Offset.Zero
+
+ private var dragTotalDistance = Offset.Zero
+
+ var containerLayoutCoordinates: LayoutCoordinates? = null
+
+ var clipboardManager: ClipboardManager? = null
+ var onSelectionChange: (Selection?) -> Unit = {}
+ var selection: Selection? = null
+
+ val observer = Observer()
+
+ inner class Observer : DragObserver {
+ override fun onStart(downPosition: Offset) {
+ mergeSelections(
+ startPosition = Offset(-1f, -1f),
+ endPosition = Offset(-1f, -1f),
+ previousSelection = selection
+ )
+ if (selection != null) onSelectionChange(null)
+ dragBeginPosition = downPosition
+ dragTotalDistance = Offset.Zero
+ }
+
+ override fun onDrag(dragDistance: Offset): Offset {
+ dragTotalDistance += dragDistance
+ val newSelection = mergeSelections(
+ startPosition = dragBeginPosition,
+ endPosition = dragBeginPosition + dragTotalDistance,
+ previousSelection = selection
+ )
+
+ if (newSelection != selection) onSelectionChange(newSelection)
+ return dragDistance
+ }
+ }
+
+ internal fun mergeSelections(
+ startPosition: Offset,
+ endPosition: Offset,
+ longPress: Boolean = false,
+ previousSelection: Selection? = null,
+ isStartHandle: Boolean = true
+ ): Selection? {
+
+ val newSelection = selectionRegistrar.sort(requireContainerCoordinates())
+ .fold(null) { mergedSelection: Selection?,
+ handler: Selectable ->
+ merge(
+ mergedSelection,
+ handler.getSelection(
+ startPosition = startPosition,
+ endPosition = endPosition,
+ containerLayoutCoordinates = requireContainerCoordinates(),
+ longPress = longPress,
+ previousSelection = previousSelection,
+ isStartHandle = isStartHandle
+ )
+ )
+ }
+ return newSelection
+ }
+
+ internal fun requireContainerCoordinates(): LayoutCoordinates {
+ val coordinates = containerLayoutCoordinates
+ require(coordinates != null)
+ require(coordinates.isAttached)
+ return coordinates
+ }
+}
+
+private fun merge(lhs: Selection?, rhs: Selection?): Selection? {
+ return lhs?.merge(rhs) ?: rhs
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionRegistrar.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionRegistrar.kt
new file mode 100644
index 0000000..7c3e79e
--- /dev/null
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/DesktopSelectionRegistrar.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.desktop
+
+import androidx.ui.core.LayoutCoordinates
+import androidx.ui.geometry.Offset
+import androidx.ui.core.selection.SelectionRegistrar
+import androidx.ui.core.selection.Selectable
+
+// based on androidx.ui.core.selection.SelectionRegistrarImpl
+internal class DesktopSelectionRegistrar : SelectionRegistrar {
+ internal var sorted: Boolean = false
+
+ private val _selectables = mutableListOf<Selectable>()
+ internal val selectables: List<Selectable>
+ get() = _selectables
+
+ internal var onPositionChangeCallback: (() -> Unit)? = null
+
+ override fun subscribe(selectable: Selectable): Selectable {
+ _selectables.add(selectable)
+ sorted = false
+ return selectable
+ }
+
+ override fun unsubscribe(selectable: Selectable) {
+ _selectables.remove(selectable)
+ }
+
+ fun sort(containerLayoutCoordinates: LayoutCoordinates): List<Selectable> {
+ if (!sorted) {
+ _selectables.sortWith(Comparator { a: Selectable, b: Selectable ->
+ val layoutCoordinatesA = a.getLayoutCoordinates()
+ val layoutCoordinatesB = b.getLayoutCoordinates()
+
+ val positionA =
+ if (layoutCoordinatesA != null) containerLayoutCoordinates.childToLocal(
+ layoutCoordinatesA,
+ Offset.Zero
+ )
+ else Offset.Zero
+ val positionB =
+ if (layoutCoordinatesB != null) containerLayoutCoordinates.childToLocal(
+ layoutCoordinatesB,
+ Offset.Zero
+ )
+ else Offset.Zero
+
+ if (positionA.y == positionB.y) compareValues(positionA.x, positionB.x)
+ else compareValues(positionA.y, positionB.y)
+ })
+ sorted = true
+ }
+ return selectables
+ }
+
+ override fun onPositionChange() {
+ sorted = false
+ onPositionChangeCallback?.invoke()
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
index aa19e73..f772d1b 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/SkiaWindow.kt
@@ -15,6 +15,8 @@
*/
package androidx.ui.desktop
+import androidx.ui.text.platform.paragraphActualFactory
+import androidx.ui.text.platform.paragraphIntrinsicsActualFactory
import com.jogamp.opengl.GL
import com.jogamp.opengl.GLAutoDrawable
import com.jogamp.opengl.GLCapabilities
@@ -22,19 +24,19 @@
import com.jogamp.opengl.GLProfile
import com.jogamp.opengl.awt.GLCanvas
import com.jogamp.opengl.util.FPSAnimator
-import org.jetbrains.skija.BackendRenderTarget
-import org.jetbrains.skija.Canvas
-import org.jetbrains.skija.Context
-import org.jetbrains.skija.JNI
-import org.jetbrains.skija.Surface
-import org.jetbrains.skija.ColorSpace
-import java.nio.IntBuffer
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseMotionAdapter
+import java.nio.IntBuffer
import javax.swing.JFrame
+import org.jetbrains.skija.BackendRenderTarget
+import org.jetbrains.skija.Canvas
+import org.jetbrains.skija.ColorSpace
+import org.jetbrains.skija.Context
+import org.jetbrains.skija.JNI
+import org.jetbrains.skija.Surface
private class SkijaState {
var context: Context? = null
@@ -75,12 +77,18 @@
height: Int,
fps: Int = 0
) : JFrame() {
+ @OptIn(androidx.ui.text.platform.InternalPlatformTextApi::class)
companion object {
init {
JNI.loadLibrary("/", "skija")
// Until https://github.com/Kotlin/kotlinx.coroutines/issues/2039 is resolved
// we have to set this property manually for coroutines to work.
System.getProperties().setProperty("kotlinx.coroutines.fast.service.loader", "false")
+
+ @Suppress("DEPRECATION_ERROR")
+ paragraphIntrinsicsActualFactory = ::DesktopParagraphIntrinsics
+ @Suppress("DEPRECATION_ERROR")
+ paragraphActualFactory = ::DesktopParagraph
}
}
diff --git a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
index 1787195..5e73423 100644
--- a/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
+++ b/ui/ui-desktop/src/jvmMain/kotlin/androidx/ui/desktop/Wrapper.kt
@@ -33,6 +33,7 @@
import androidx.lifecycle.ViewTreeViewModelStoreOwner
import androidx.ui.core.setContent
import androidx.ui.core.TextInputServiceAmbient
+import androidx.ui.core.FontLoaderAmbient
import androidx.ui.input.TextInputService
import javax.swing.SwingUtilities
@@ -63,13 +64,17 @@
throw IllegalStateException("ViewModels creation is not supported")
})
viewGroup.setContent(Recomposer.current(), @Composable {
- Providers(TextInputServiceAmbient provides TextInputService(
- platformInputService), children = content)
+ Providers(
+ TextInputServiceAmbient provides TextInputService(
+ platformInputService),
+ FontLoaderAmbient provides FontLoader()
+ ) {
+ DesktopSelectionContainer(children = content)
+ }
})
- val view = viewGroup.getChildAt(0)
- view.onAttachedToWindow()
+ viewGroup.onAttachedToWindow()
- this.renderer = Renderer(view, clocks, fps, platformInputService)
+ this.renderer = Renderer(viewGroup.getChildAt(0), clocks, fps, platformInputService)
this.setFps(fps)
}
}
diff --git a/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/Runner.kt b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/Runner.kt
new file mode 100644
index 0000000..02f8d34
--- /dev/null
+++ b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/Runner.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.desktop
+
+import org.junit.runner.JUnitCore
+import org.junit.internal.TextListener
+
+fun main() {
+ val junit = JUnitCore()
+ junit.addListener(TextListener(System.out))
+ junit.run(WrapperTest::class.java)
+ System.exit(0)
+}
\ No newline at end of file
diff --git a/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/WrapperTest.kt b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/WrapperTest.kt
new file mode 100644
index 0000000..a89a873
--- /dev/null
+++ b/ui/ui-desktop/src/jvmTest/kotlin/androidx/ui/desktop/WrapperTest.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.desktop
+
+import androidx.ui.foundation.Text
+
+import java.awt.event.WindowEvent
+import javax.swing.WindowConstants
+
+import org.junit.Test
+
+class WrapperTest {
+ @Test
+ fun wrapWindow() {
+ val frame = SkiaWindow(width = 640, height = 480)
+
+ frame.title = "Test"
+ frame.setLocation(400, 400)
+ frame.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
+
+ frame.setContent {
+ Text("Simple")
+ }
+ frame.setVisible(true)
+
+ frame.dispatchEvent(WindowEvent(frame, WindowEvent.WINDOW_CLOSING))
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-foundation/api/0.1.0-dev15.txt b/ui/ui-foundation/api/0.1.0-dev15.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/0.1.0-dev15.txt
+++ b/ui/ui-foundation/api/0.1.0-dev15.txt
@@ -25,7 +25,6 @@
}
public final class ClickableKt {
- method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
}
public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
}
public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
}
@androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
property public final boolean isAnimating;
property public final float maxPosition;
property public final float value;
- field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+ field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
}
public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
property public final String Selected;
property public final String TemplatePercent;
property public final String Unchecked;
- field public static final androidx.ui.foundation.Strings! INSTANCE;
+ field public static final androidx.ui.foundation.Strings INSTANCE;
}
public final class TemporaryKt {
@@ -177,7 +176,7 @@
method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
method @Deprecated public androidx.ui.text.TextRange getSelection();
method @Deprecated public String getText();
- field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+ field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
}
@Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
public final class AndroidFlingSpline {
method public double deceleration(float velocity, float friction);
method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
- field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+ field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
}
public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
}
public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
}
public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
}
public final class DraggableKt {
@@ -327,16 +326,13 @@
package androidx.ui.foundation.selection {
public final class SelectableKt {
- method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ToggleableKt {
- method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
- method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
}
public enum ToggleableState {
+ method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.foundation.selection.ToggleableState[] values();
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
- field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
}
public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/current.txt b/ui/ui-foundation/api/current.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/current.txt
+++ b/ui/ui-foundation/api/current.txt
@@ -25,7 +25,6 @@
}
public final class ClickableKt {
- method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
}
public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
}
public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
}
@androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
property public final boolean isAnimating;
property public final float maxPosition;
property public final float value;
- field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+ field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
}
public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
property public final String Selected;
property public final String TemplatePercent;
property public final String Unchecked;
- field public static final androidx.ui.foundation.Strings! INSTANCE;
+ field public static final androidx.ui.foundation.Strings INSTANCE;
}
public final class TemporaryKt {
@@ -177,7 +176,7 @@
method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
method @Deprecated public androidx.ui.text.TextRange getSelection();
method @Deprecated public String getText();
- field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+ field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
}
@Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
public final class AndroidFlingSpline {
method public double deceleration(float velocity, float friction);
method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
- field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+ field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
}
public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
}
public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
}
public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
}
public final class DraggableKt {
@@ -327,16 +326,13 @@
package androidx.ui.foundation.selection {
public final class SelectableKt {
- method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ToggleableKt {
- method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
- method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
}
public enum ToggleableState {
+ method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.foundation.selection.ToggleableState[] values();
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
- field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
}
public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
@@ -25,7 +25,6 @@
}
public final class ClickableKt {
- method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
}
public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
}
public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
}
@androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
property public final boolean isAnimating;
property public final float maxPosition;
property public final float value;
- field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+ field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
}
public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
property public final String Selected;
property public final String TemplatePercent;
property public final String Unchecked;
- field public static final androidx.ui.foundation.Strings! INSTANCE;
+ field public static final androidx.ui.foundation.Strings INSTANCE;
}
public final class TemporaryKt {
@@ -177,7 +176,7 @@
method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
method @Deprecated public androidx.ui.text.TextRange getSelection();
method @Deprecated public String getText();
- field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+ field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
}
@Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
public final class AndroidFlingSpline {
method public double deceleration(float velocity, float friction);
method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
- field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+ field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
}
public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
}
public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
}
public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
}
public final class DraggableKt {
@@ -327,16 +326,13 @@
package androidx.ui.foundation.selection {
public final class SelectableKt {
- method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ToggleableKt {
- method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
- method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
}
public enum ToggleableState {
+ method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.foundation.selection.ToggleableState[] values();
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
- field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
}
public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/public_plus_experimental_current.txt b/ui/ui-foundation/api/public_plus_experimental_current.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/public_plus_experimental_current.txt
+++ b/ui/ui-foundation/api/public_plus_experimental_current.txt
@@ -25,7 +25,6 @@
}
public final class ClickableKt {
- method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
}
public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
}
public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
}
@androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
property public final boolean isAnimating;
property public final float maxPosition;
property public final float value;
- field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+ field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
}
public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
property public final String Selected;
property public final String TemplatePercent;
property public final String Unchecked;
- field public static final androidx.ui.foundation.Strings! INSTANCE;
+ field public static final androidx.ui.foundation.Strings INSTANCE;
}
public final class TemporaryKt {
@@ -177,7 +176,7 @@
method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
method @Deprecated public androidx.ui.text.TextRange getSelection();
method @Deprecated public String getText();
- field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+ field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
}
@Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
public final class AndroidFlingSpline {
method public double deceleration(float velocity, float friction);
method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
- field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+ field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
}
public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
}
public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
}
public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
}
public final class DraggableKt {
@@ -327,16 +326,13 @@
package androidx.ui.foundation.selection {
public final class SelectableKt {
- method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ToggleableKt {
- method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
- method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
}
public enum ToggleableState {
+ method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.foundation.selection.ToggleableState[] values();
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
- field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
}
public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/restricted_0.1.0-dev15.txt b/ui/ui-foundation/api/restricted_0.1.0-dev15.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-foundation/api/restricted_0.1.0-dev15.txt
@@ -25,7 +25,6 @@
}
public final class ClickableKt {
- method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
}
public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
}
public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
}
@androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
property public final boolean isAnimating;
property public final float maxPosition;
property public final float value;
- field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+ field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
}
public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
property public final String Selected;
property public final String TemplatePercent;
property public final String Unchecked;
- field public static final androidx.ui.foundation.Strings! INSTANCE;
+ field public static final androidx.ui.foundation.Strings INSTANCE;
}
public final class TemporaryKt {
@@ -177,7 +176,7 @@
method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
method @Deprecated public androidx.ui.text.TextRange getSelection();
method @Deprecated public String getText();
- field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+ field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
}
@Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
public final class AndroidFlingSpline {
method public double deceleration(float velocity, float friction);
method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
- field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+ field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
}
public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
}
public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
}
public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
}
public final class DraggableKt {
@@ -327,16 +326,13 @@
package androidx.ui.foundation.selection {
public final class SelectableKt {
- method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ToggleableKt {
- method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
- method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
}
public enum ToggleableState {
+ method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.foundation.selection.ToggleableState[] values();
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
- field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
}
public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/api/restricted_current.txt b/ui/ui-foundation/api/restricted_current.txt
index 37de57e..b324b25 100644
--- a/ui/ui-foundation/api/restricted_current.txt
+++ b/ui/ui-foundation/api/restricted_current.txt
@@ -25,7 +25,6 @@
}
public final class ClickableKt {
- method @Deprecated @androidx.compose.Composable public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState? interactionState = null, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier clickable(androidx.ui.core.Modifier, boolean enabled = true, String? onClickLabel = null, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick = null, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
@@ -100,11 +99,11 @@
}
public static final class Interaction.Dragged implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Dragged! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Dragged INSTANCE;
}
public static final class Interaction.Pressed implements androidx.ui.foundation.Interaction {
- field public static final androidx.ui.foundation.Interaction.Pressed! INSTANCE;
+ field public static final androidx.ui.foundation.Interaction.Pressed INSTANCE;
}
@androidx.compose.Stable public final class InteractionState implements androidx.compose.State<java.util.Set<? extends androidx.ui.foundation.Interaction>> {
@@ -135,7 +134,7 @@
property public final boolean isAnimating;
property public final float maxPosition;
property public final float value;
- field public static final androidx.ui.foundation.ScrollerPosition.Companion! Companion;
+ field public static final androidx.ui.foundation.ScrollerPosition.Companion Companion;
}
public static final class ScrollerPosition.Companion {
@@ -157,7 +156,7 @@
property public final String Selected;
property public final String TemplatePercent;
property public final String Unchecked;
- field public static final androidx.ui.foundation.Strings! INSTANCE;
+ field public static final androidx.ui.foundation.Strings INSTANCE;
}
public final class TemporaryKt {
@@ -177,7 +176,7 @@
method @Deprecated @androidx.compose.Immutable public androidx.ui.foundation.TextFieldValue copy(String text, androidx.ui.text.TextRange selection);
method @Deprecated public androidx.ui.text.TextRange getSelection();
method @Deprecated public String getText();
- field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion! Companion;
+ field @Deprecated public static final androidx.ui.foundation.TextFieldValue.Companion Companion;
}
@Deprecated public static final class TextFieldValue.Companion {
@@ -235,7 +234,7 @@
public final class AndroidFlingSpline {
method public double deceleration(float velocity, float friction);
method public androidx.ui.foundation.animation.AndroidFlingSpline.FlingResult flingPosition(float time);
- field public static final androidx.ui.foundation.animation.AndroidFlingSpline! INSTANCE;
+ field public static final androidx.ui.foundation.animation.AndroidFlingSpline INSTANCE;
}
public static final class AndroidFlingSpline.FlingResult {
@@ -275,11 +274,11 @@
}
public static final class DragDirection.Horizontal extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Horizontal INSTANCE;
}
public static final class DragDirection.Vertical extends androidx.ui.foundation.gestures.DragDirection {
- field public static final androidx.ui.foundation.gestures.DragDirection.Vertical! INSTANCE;
+ field public static final androidx.ui.foundation.gestures.DragDirection.Vertical INSTANCE;
}
public final class DraggableKt {
@@ -327,16 +326,13 @@
package androidx.ui.foundation.selection {
public final class SelectableKt {
- method @Deprecated @androidx.compose.Composable public static void MutuallyExclusiveSetItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier selectable(androidx.ui.core.Modifier, boolean selected, boolean enabled = true, boolean inMutuallyExclusiveGroup = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ToggleableKt {
- method @Deprecated @androidx.compose.Composable public static void Toggleable(boolean value, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static androidx.ui.foundation.selection.ToggleableState ToggleableState(boolean value);
- method @Deprecated @androidx.compose.Composable public static void TriStateToggleable(androidx.ui.foundation.selection.ToggleableState state = androidx.ui.foundation.selection.ToggleableState.On, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, boolean enabled = true, androidx.ui.core.Modifier modifier = Modifier, kotlin.jvm.functions.Function0<kotlin.Unit> children);
method @androidx.compose.Composable public static androidx.ui.core.Modifier toggleable(androidx.ui.core.Modifier, boolean value, boolean enabled = true, androidx.ui.foundation.InteractionState interactionState = remember({
return <init>()
}), androidx.ui.foundation.Indication? indication = IndicationAmbient.invoke(), kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onValueChange);
@@ -346,6 +342,8 @@
}
public enum ToggleableState {
+ method public static androidx.ui.foundation.selection.ToggleableState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.foundation.selection.ToggleableState[] values();
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Indeterminate;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState Off;
enum_constant public static final androidx.ui.foundation.selection.ToggleableState On;
@@ -364,7 +362,7 @@
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> IsDialog;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> Selected;
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.foundation.selection.ToggleableState> ToggleableState;
- field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.foundation.semantics.FoundationSemanticsProperties INSTANCE;
}
public final class FoundationSemanticsPropertiesKt {
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
index 5543260..e68b163 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
@@ -20,7 +20,6 @@
import androidx.compose.onCommit
import androidx.compose.remember
import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
import androidx.ui.core.PointerEventPass
import androidx.ui.core.PointerInputChange
import androidx.ui.core.anyPositionChangeConsumed
@@ -41,65 +40,6 @@
import androidx.ui.util.fastAny
/**
- * Combines [tapGestureFilter] and Semantics for the clickable
- * components like Button.
- *
- * @sample androidx.ui.foundation.samples.ClickableSample
- *
- * @param onClick will be called when user clicked on the button
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- * @param enabled Controls the enabled state. When `false`, this component will not be
- * clickable
- * @param onClickLabel semantic / accessibility label for the [onClick] action
- * @param interactionState [InteractionState] that will be updated when this Clickable is
- * pressed, using [Interaction.Pressed]. Only initial (first) press will be recorded and added to
- * [InteractionState]
- *
- * @deprecated Use [clickable] modifier instead
- */
-@Deprecated(
- "Clickable has been deprecated, use clickable modifier instead",
- ReplaceWith(
- "Box(modifier.clickable(onClick = onClick, enabled = enabled), children = children)",
- "androidx.foundation.clickable",
- "androidx.foundation.Box"
- )
-)
-@Composable
-fun Clickable(
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
- enabled: Boolean = true,
- onClickLabel: String? = null,
- interactionState: InteractionState? = null,
- children: @Composable () -> Unit
-) {
- @Suppress("DEPRECATION")
- PassThroughLayout(
- modifier.clickable(
- enabled,
- onClickLabel,
- tempFunToAvoidCreatingLambdaInsideClickable(interactionState),
- onClick = onClick
- ),
- children
- )
-}
-
-// when there is a lambda inside Clickable it is created as a file $Clickable\$2.class which
-// conflicts with similar lambda from Modifier.clickable which stored in $clickable\$2.class
-// on the case-insensitive FS. proper workaround would be to use different @JvmName on these
-// functions but it is currently not supported for composables b/157075847
-@Composable
-private fun tempFunToAvoidCreatingLambdaInsideClickable(
- interactionState: InteractionState?
-): InteractionState {
- return interactionState ?: remember { InteractionState() }
-}
-
-/**
* Configure component to receive clicks via input or accessibility "click" event.
*
* Add this modifier to the element to make it clickable within its bounds.
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
index ae2c322..265a3e9 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/TextField.kt
@@ -55,6 +55,7 @@
import androidx.ui.text.TextLayoutResult
import androidx.ui.text.TextRange
import androidx.ui.text.TextStyle
+import androidx.ui.text.constrain
import androidx.ui.unit.dp
import org.jetbrains.annotations.TestOnly
@@ -129,13 +130,10 @@
) {
val fullModel = state { androidx.ui.input.TextFieldValue() }
if (fullModel.value.text != value.text || fullModel.value.selection != value.selection) {
- val newSelection = TextRange(
- value.selection.start.coerceIn(0, value.text.length),
- value.selection.end.coerceIn(0, value.text.length)
- )
+ @OptIn(InternalTextApi::class)
fullModel.value = androidx.ui.input.TextFieldValue(
text = value.text,
- selection = newSelection
+ selection = value.selection.constrain(0, value.text.length)
)
}
@@ -249,14 +247,11 @@
) {
val fullModel = state { androidx.ui.input.TextFieldValue() }
if (fullModel.value != value) {
- val newSelection = TextRange(
- value.selection.start.coerceIn(0, value.text.length),
- value.selection.end.coerceIn(0, value.text.length)
- )
+ @OptIn(InternalTextApi::class)
fullModel.value = androidx.ui.input.TextFieldValue(
text = value.text,
- selection = newSelection,
- composition = value.composition
+ selection = value.selection.constrain(0, value.text.length),
+ composition = value.composition?.constrain(0, value.text.length)
)
}
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt
index 149e58b..d077b8c 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItems.kt
@@ -20,15 +20,18 @@
import androidx.compose.ExperimentalComposeApi
import androidx.compose.compositionReference
import androidx.compose.currentComposer
+import androidx.compose.emit
import androidx.compose.onDispose
import androidx.compose.remember
-import androidx.ui.core.ContextAmbient
+import androidx.ui.core.LayoutNode
import androidx.ui.core.Modifier
+import androidx.ui.core.Ref
import androidx.ui.core.clipToBounds
import androidx.ui.core.materialize
import androidx.ui.foundation.gestures.DragDirection
import androidx.ui.foundation.gestures.scrollable
import androidx.ui.layout.Spacer
+import androidx.ui.node.UiApplier
/**
* A vertically scrolling list that only composes and lays out the currently visible items.
@@ -80,28 +83,42 @@
state.recomposer = currentComposer.recomposer
state.itemContent = itemContent
state.items = items
- state.context = ContextAmbient.current
state.compositionRef = compositionReference()
state.forceRecompose = true
val dragDirection = if (isVertical) DragDirection.Vertical else DragDirection.Horizontal
- androidx.ui.core.LayoutNode(
- modifier = currentComposer.materialize(
- modifier
- .scrollable(
- dragDirection = dragDirection,
- scrollableState = androidx.ui.foundation.gestures.ScrollableState(
- onScrollDeltaConsumptionRequested =
- state.onScrollDeltaConsumptionRequestedListener
- )
+ val materialized = currentComposer.materialize(
+ modifier
+ .scrollable(
+ dragDirection = dragDirection,
+ scrollableState = androidx.ui.foundation.gestures.ScrollableState(
+ onScrollDeltaConsumptionRequested =
+ state.onScrollDeltaConsumptionRequestedListener
)
- .clipToBounds()
- ),
- ref = state.rootNodeRef,
- measureBlocks = state.measureBlocks
+ )
+ .clipToBounds()
+ )
+ emit<LayoutNode, UiApplier>(
+ ctor = LayoutEmitHelper.constructor,
+ update = {
+ set(materialized, LayoutEmitHelper.setModifier)
+ set(state.rootNodeRef, LayoutEmitHelper.setRef)
+ set(state.measureBlocks, LayoutEmitHelper.setMeasureBlocks)
+ }
)
state.recomposeIfAttached()
onDispose {
state.disposeAllChildren()
}
}
+
+/**
+ * Object of pre-allocated lambdas used to make emits to LayoutNodes allocation-less.
+ */
+private object LayoutEmitHelper {
+ val constructor: () -> LayoutNode = { LayoutNode() }
+ val setModifier: LayoutNode.(Modifier) -> Unit = { this.modifier = it }
+ val setMeasureBlocks: LayoutNode.(LayoutNode.MeasureBlocks) -> Unit =
+ { this.measureBlocks = it }
+ val setRef: LayoutNode.(Ref<LayoutNode>) -> Unit = { this.ref = it }
+}
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt
index ad9399b..50d0d0e 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/lazy/LazyItemsState.kt
@@ -16,14 +16,13 @@
package androidx.ui.foundation.lazy
-import android.content.Context
import androidx.compose.Composable
+import androidx.compose.ComposableContract
import androidx.compose.Composition
import androidx.compose.CompositionReference
import androidx.compose.ExperimentalComposeApi
import androidx.compose.FrameManager
import androidx.compose.Recomposer
-import androidx.compose.Untracked
import androidx.ui.core.Constraints
import androidx.ui.core.LayoutDirection
import androidx.ui.core.LayoutNode
@@ -58,10 +57,6 @@
var forceRecompose = false
var compositionRef: CompositionReference? = null
/**
- * Should always be non-null when attached
- */
- var context: Context? = null
- /**
* Used to get the reference to populate [rootNode]
*/
val rootNodeRef = Ref<LayoutNode>()
@@ -473,9 +468,13 @@
} else {
node = rootNode.children[layoutIndex.value]
}
- // TODO(b/150390669): Review use of @Untracked
+ // TODO(b/150390669): Review use of @ComposableContract(tracked = false)
@OptIn(ExperimentalComposeApi::class)
- val composition = subcomposeInto(context!!, node, recomposer, compositionRef) @Untracked {
+ val composition = subcomposeInto(
+ node,
+ recomposer,
+ compositionRef
+ ) @ComposableContract(tracked = false) {
itemContent(items[dataIndex.value])
}
compositionsForLayoutNodes[node] = composition
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
index 74acf8d..cac46d7 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
@@ -19,11 +19,8 @@
import androidx.compose.Composable
import androidx.compose.remember
import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
import androidx.ui.core.composed
-import androidx.ui.core.gesture.tapGestureFilter
import androidx.ui.core.semantics.semantics
-import androidx.ui.foundation.Box
import androidx.ui.foundation.Indication
import androidx.ui.foundation.IndicationAmbient
import androidx.ui.foundation.Interaction
@@ -36,55 +33,6 @@
import androidx.ui.semantics.onClick
/**
- * Component for representing one option out of many
- * in mutually exclusion set, e.g [androidx.ui.material.RadioGroup]
- *
- * Provides click handling as well as [Modifier.semantics] for accessibility
- *
- * @param selected whether or not this item is selected in mutually exclusion set
- * @param onClick callback to invoke when this item is clicked
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- *
- * @Deprecated Use [Modifier.selectable] instead.
- */
-@Deprecated(
- "MutuallyExclusiveSetItem has been deprecated, use Modifier.selectable " +
- "instead",
- ReplaceWith(
- "Box(modifier.selectable(" +
- "selected = selected, " +
- "onClick = onClick" +
- ")," +
- " children = children)",
- "androidx.foundation.selectable",
- "androidx.foundation.Box"
- )
-)
-@Composable
-fun MutuallyExclusiveSetItem(
- selected: Boolean,
- onClick: () -> Unit,
- modifier: Modifier = Modifier,
- children: @Composable () -> Unit
-) {
- // TODO: when semantics can be merged, we should make this use Clickable internally rather
- // than duplicating logic
- Box(Modifier.semantics {
- inMutuallyExclusiveGroup = true
- this.selected = selected
- this.accessibilityValue = if (selected) Strings.Selected else Strings.NotSelected
- onClick(action = { onClick(); return@onClick true })
- }) {
- // TODO(b/150706555): This layout is temporary and should be removed once Semantics
- // is implemented with modifiers.
- @Suppress("DEPRECATION")
- PassThroughLayout(modifier.tapGestureFilter { onClick() }, children)
- }
-}
-
-/**
* Configure component to be selectable, usually as a part of a mutually exclusive group, where
* only one item can be selected at any point in time. A typical example of mutually exclusive set
* is [androidx.ui.material.RadioGroup]
diff --git a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
index da91357..00fe81f 100644
--- a/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
+++ b/ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
@@ -20,7 +20,6 @@
import androidx.compose.onCommit
import androidx.compose.remember
import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
import androidx.ui.core.composed
import androidx.ui.core.gesture.pressIndicatorGestureFilter
import androidx.ui.core.gesture.tapGestureFilter
@@ -40,49 +39,6 @@
import androidx.ui.semantics.onClick
/**
- * Combines [tapGestureFilter] and [Modifier.semantics] for the components that need to be
- * toggleable, like Switch.
- *
- * @see [TriStateToggleable] if you require support for an indeterminate state.
- *
- * @param value whether Toggleable is on or off
- * @param onValueChange callback to be invoked when toggleable is clicked,
- * therefore the change of the state in requested.
- * @param enabled whether or not this [Toggleable] will handle input events and appear
- * enabled for semantics purposes
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- * @Deprecated Use [Modifier.toggleable] instead.
- */
-@Deprecated(
- "This component has been deprecated. Use [Modifier.toggleable] instead.",
- ReplaceWith(
- "Box(modifier.toggleable(" +
- "value = value," +
- " onValueChange = onValueChange," +
- " enabled = enabled" +
- "), children = children)",
- "androidx.foundation.toggleable",
- "androidx.foundation.Box"
- )
-)
-@Composable
-fun Toggleable(
- value: Boolean,
- onValueChange: (Boolean) -> Unit,
- enabled: Boolean = true,
- modifier: Modifier = Modifier,
- children: @Composable () -> Unit
-) {
- @Suppress("DEPRECATION")
- PassThroughLayout(
- modifier.toggleable(value = value, onValueChange = onValueChange, enabled = enabled),
- children
- )
-}
-
-/**
* Configure component to make it toggleable via input and accessibility events
*
* @sample androidx.ui.foundation.samples.ToggleableSample
@@ -115,54 +71,6 @@
)
/**
- * Combines [tapGestureFilter] and [Modifier.semantics] for the components with three states
- * like TriStateCheckbox.
- *
- * It supports three states: On, Off and Indeterminate.
- *
- * TriStateToggleable should be used when there are
- * dependent Toggleables associated to this component and those can have different values.
- *
- * @see [Toggleable] if you want to support only two states: on and off
- *
- * @param state current value for the component
- * @param onClick will be called when user toggles the toggleable.
- * @param enabled whether or not this [TriStateToggleable] will handle input events and
- * appear enabled for semantics purposes
- * @param modifier allows to provide a modifier to be added before the gesture detector, for
- * example Ripple should be added at this point. this will be easier once we migrate this
- * function to a Modifier
- *
- * @Deprecated Use [Modifier.triStateToggleable] instead.
- */
-@Deprecated(
- "This component has been deprecated. Use [Modifier.triStateToggleable] instead.",
- ReplaceWith(
- "Box(modifier.triStateToggleable(" +
- "state = state," +
- " onClick = onClick," +
- " enabled = enabled" +
- "), children = children)",
- "androidx.foundation.triStateToggleable",
- "androidx.foundation.Box"
- )
-)
-@Composable
-fun TriStateToggleable(
- state: ToggleableState = On,
- onClick: () -> Unit,
- enabled: Boolean = true,
- modifier: Modifier = Modifier,
- children: @Composable () -> Unit
-) {
- @Suppress("DEPRECATION")
- PassThroughLayout(
- modifier.triStateToggleable(state = state, onClick = onClick, enabled = enabled),
- children
- )
-}
-
-/**
* Configure component to make it toggleable via input and accessibility events with three
* states: On, Off and Indeterminate.
*
diff --git a/ui/ui-geometry/api/0.1.0-dev15.txt b/ui/ui-geometry/api/0.1.0-dev15.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/0.1.0-dev15.txt
+++ b/ui/ui-geometry/api/0.1.0-dev15.txt
@@ -17,7 +17,7 @@
method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
property public final float x;
property public final float y;
- field public static final androidx.ui.geometry.Offset.Companion! Companion;
+ field public static final androidx.ui.geometry.Offset.Companion Companion;
}
public static final class Offset.Companion {
@@ -78,7 +78,7 @@
method public static androidx.ui.geometry.RRect getZero();
property public final float height;
property public final float width;
- field public static final androidx.ui.geometry.RRect.Companion! Companion;
+ field public static final androidx.ui.geometry.RRect.Companion Companion;
}
public static final class RRect.Companion {
@@ -135,7 +135,7 @@
method public static String toString-impl(long $this);
method public static long truncDiv-impl(long $this, float operand);
method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.geometry.Radius.Companion! Companion;
+ field public static final androidx.ui.geometry.Radius.Companion Companion;
}
public static final class Radius.Companion {
@@ -189,7 +189,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Rect.Companion! Companion;
+ field public static final androidx.ui.geometry.Rect.Companion Companion;
}
public static final class Rect.Companion {
@@ -239,7 +239,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Size.Companion! Companion;
+ field public static final androidx.ui.geometry.Size.Companion Companion;
}
public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/api_lint.ignore b/ui/ui-geometry/api/api_lint.ignore
index c3e3a08..db1ca8b 100644
--- a/ui/ui-geometry/api/api_lint.ignore
+++ b/ui/ui-geometry/api/api_lint.ignore
@@ -3,3 +3,11 @@
Acronyms should not be capitalized in method names: was `fromLTRB`, should this be `fromLtrb`?
AcronymName: androidx.ui.geometry.Rect.Companion#fromLTWH(float, float, float, float):
Acronyms should not be capitalized in method names: was `fromLTWH`, should this be `fromLtwh`?
+
+
+KotlinOperator: androidx.ui.geometry.RRect#contains(androidx.ui.geometry.Offset):
+ Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.ui.geometry.Rect#contains(androidx.ui.geometry.Offset):
+ Note that adding the `operator` keyword would allow calling this method using operator syntax
+KotlinOperator: androidx.ui.geometry.Size#contains(androidx.ui.geometry.Offset):
+ Note that adding the `operator` keyword would allow calling this method using operator syntax
diff --git a/ui/ui-geometry/api/current.txt b/ui/ui-geometry/api/current.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/current.txt
+++ b/ui/ui-geometry/api/current.txt
@@ -17,7 +17,7 @@
method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
property public final float x;
property public final float y;
- field public static final androidx.ui.geometry.Offset.Companion! Companion;
+ field public static final androidx.ui.geometry.Offset.Companion Companion;
}
public static final class Offset.Companion {
@@ -78,7 +78,7 @@
method public static androidx.ui.geometry.RRect getZero();
property public final float height;
property public final float width;
- field public static final androidx.ui.geometry.RRect.Companion! Companion;
+ field public static final androidx.ui.geometry.RRect.Companion Companion;
}
public static final class RRect.Companion {
@@ -135,7 +135,7 @@
method public static String toString-impl(long $this);
method public static long truncDiv-impl(long $this, float operand);
method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.geometry.Radius.Companion! Companion;
+ field public static final androidx.ui.geometry.Radius.Companion Companion;
}
public static final class Radius.Companion {
@@ -189,7 +189,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Rect.Companion! Companion;
+ field public static final androidx.ui.geometry.Rect.Companion Companion;
}
public static final class Rect.Companion {
@@ -239,7 +239,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Size.Companion! Companion;
+ field public static final androidx.ui.geometry.Size.Companion Companion;
}
public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-geometry/api/public_plus_experimental_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
property public final float x;
property public final float y;
- field public static final androidx.ui.geometry.Offset.Companion! Companion;
+ field public static final androidx.ui.geometry.Offset.Companion Companion;
}
public static final class Offset.Companion {
@@ -78,7 +78,7 @@
method public static androidx.ui.geometry.RRect getZero();
property public final float height;
property public final float width;
- field public static final androidx.ui.geometry.RRect.Companion! Companion;
+ field public static final androidx.ui.geometry.RRect.Companion Companion;
}
public static final class RRect.Companion {
@@ -135,7 +135,7 @@
method public static String toString-impl(long $this);
method public static long truncDiv-impl(long $this, float operand);
method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.geometry.Radius.Companion! Companion;
+ field public static final androidx.ui.geometry.Radius.Companion Companion;
}
public static final class Radius.Companion {
@@ -189,7 +189,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Rect.Companion! Companion;
+ field public static final androidx.ui.geometry.Rect.Companion Companion;
}
public static final class Rect.Companion {
@@ -239,7 +239,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Size.Companion! Companion;
+ field public static final androidx.ui.geometry.Size.Companion Companion;
}
public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/public_plus_experimental_current.txt b/ui/ui-geometry/api/public_plus_experimental_current.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/public_plus_experimental_current.txt
+++ b/ui/ui-geometry/api/public_plus_experimental_current.txt
@@ -17,7 +17,7 @@
method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
property public final float x;
property public final float y;
- field public static final androidx.ui.geometry.Offset.Companion! Companion;
+ field public static final androidx.ui.geometry.Offset.Companion Companion;
}
public static final class Offset.Companion {
@@ -78,7 +78,7 @@
method public static androidx.ui.geometry.RRect getZero();
property public final float height;
property public final float width;
- field public static final androidx.ui.geometry.RRect.Companion! Companion;
+ field public static final androidx.ui.geometry.RRect.Companion Companion;
}
public static final class RRect.Companion {
@@ -135,7 +135,7 @@
method public static String toString-impl(long $this);
method public static long truncDiv-impl(long $this, float operand);
method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.geometry.Radius.Companion! Companion;
+ field public static final androidx.ui.geometry.Radius.Companion Companion;
}
public static final class Radius.Companion {
@@ -189,7 +189,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Rect.Companion! Companion;
+ field public static final androidx.ui.geometry.Rect.Companion Companion;
}
public static final class Rect.Companion {
@@ -239,7 +239,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Size.Companion! Companion;
+ field public static final androidx.ui.geometry.Size.Companion Companion;
}
public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/restricted_0.1.0-dev15.txt b/ui/ui-geometry/api/restricted_0.1.0-dev15.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-geometry/api/restricted_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
property public final float x;
property public final float y;
- field public static final androidx.ui.geometry.Offset.Companion! Companion;
+ field public static final androidx.ui.geometry.Offset.Companion Companion;
}
public static final class Offset.Companion {
@@ -78,7 +78,7 @@
method public static androidx.ui.geometry.RRect getZero();
property public final float height;
property public final float width;
- field public static final androidx.ui.geometry.RRect.Companion! Companion;
+ field public static final androidx.ui.geometry.RRect.Companion Companion;
}
public static final class RRect.Companion {
@@ -135,7 +135,7 @@
method public static String toString-impl(long $this);
method public static long truncDiv-impl(long $this, float operand);
method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.geometry.Radius.Companion! Companion;
+ field public static final androidx.ui.geometry.Radius.Companion Companion;
}
public static final class Radius.Companion {
@@ -189,7 +189,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Rect.Companion! Companion;
+ field public static final androidx.ui.geometry.Rect.Companion Companion;
}
public static final class Rect.Companion {
@@ -239,7 +239,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Size.Companion! Companion;
+ field public static final androidx.ui.geometry.Size.Companion Companion;
}
public static final class Size.Companion {
diff --git a/ui/ui-geometry/api/restricted_current.txt b/ui/ui-geometry/api/restricted_current.txt
index 6420059..f20e212 100644
--- a/ui/ui-geometry/api/restricted_current.txt
+++ b/ui/ui-geometry/api/restricted_current.txt
@@ -17,7 +17,7 @@
method @androidx.compose.Stable public operator androidx.ui.geometry.Offset unaryMinus();
property public final float x;
property public final float y;
- field public static final androidx.ui.geometry.Offset.Companion! Companion;
+ field public static final androidx.ui.geometry.Offset.Companion Companion;
}
public static final class Offset.Companion {
@@ -78,7 +78,7 @@
method public static androidx.ui.geometry.RRect getZero();
property public final float height;
property public final float width;
- field public static final androidx.ui.geometry.RRect.Companion! Companion;
+ field public static final androidx.ui.geometry.RRect.Companion Companion;
}
public static final class RRect.Companion {
@@ -135,7 +135,7 @@
method public static String toString-impl(long $this);
method public static long truncDiv-impl(long $this, float operand);
method @androidx.compose.Stable public static operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.geometry.Radius.Companion! Companion;
+ field public static final androidx.ui.geometry.Radius.Companion Companion;
}
public static final class Radius.Companion {
@@ -189,7 +189,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Rect.Companion! Companion;
+ field public static final androidx.ui.geometry.Rect.Companion Companion;
}
public static final class Rect.Companion {
@@ -239,7 +239,7 @@
property public final float maxDimension;
property public final float minDimension;
property public final float width;
- field public static final androidx.ui.geometry.Size.Companion! Companion;
+ field public static final androidx.ui.geometry.Size.Companion Companion;
}
public static final class Size.Companion {
diff --git a/ui/ui-graphics/api/0.1.0-dev15.txt b/ui/ui-graphics/api/0.1.0-dev15.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/0.1.0-dev15.txt
+++ b/ui/ui-graphics/api/0.1.0-dev15.txt
@@ -44,14 +44,14 @@
method public android.graphics.Path getInternalPath();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType value);
method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
}
public enum BlendMode {
+ method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.BlendMode[] values();
enum_constant public static final androidx.ui.graphics.BlendMode clear;
enum_constant public static final androidx.ui.graphics.BlendMode color;
enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
}
public enum ClipOp {
+ method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ClipOp[] values();
enum_constant public static final androidx.ui.graphics.ClipOp difference;
enum_constant public static final androidx.ui.graphics.ClipOp intersect;
}
@@ -198,7 +202,7 @@
method public long getValue();
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method public static String toString-impl(long $this);
- field public static final androidx.ui.graphics.Color.Companion! Companion;
+ field public static final androidx.ui.graphics.Color.Companion Companion;
}
public static final class Color.Companion {
@@ -236,7 +240,7 @@
method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
method public androidx.ui.graphics.BlendMode getBlendMode();
method public long getColor();
- field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+ field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
}
public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
}
public enum FilterQuality {
+ method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.FilterQuality[] values();
enum_constant public static final androidx.ui.graphics.FilterQuality high;
enum_constant public static final androidx.ui.graphics.FilterQuality low;
enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
}
public enum ImageAssetConfig {
+ method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ImageAssetConfig[] values();
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
}
public enum PaintingStyle {
+ method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PaintingStyle[] values();
enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
}
@@ -395,21 +405,21 @@
method public androidx.ui.graphics.PathFillType getFillType();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType p);
method public void shift(androidx.ui.geometry.Offset offset);
property public abstract androidx.ui.graphics.PathFillType fillType;
property public abstract boolean isConvex;
property public abstract boolean isEmpty;
- field public static final androidx.ui.graphics.Path.Companion! Companion;
+ field public static final androidx.ui.graphics.Path.Companion Companion;
}
public static final class Path.Companion {
@@ -417,11 +427,15 @@
}
public enum PathFillType {
+ method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathFillType[] values();
enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
}
public enum PathOperation {
+ method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathOperation[] values();
enum_constant public static final androidx.ui.graphics.PathOperation difference;
enum_constant public static final androidx.ui.graphics.PathOperation intersect;
enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
}
public enum PointMode {
+ method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PointMode[] values();
enum_constant public static final androidx.ui.graphics.PointMode lines;
enum_constant public static final androidx.ui.graphics.PointMode points;
enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
method public float getBlurRadius();
method public long getColor();
method public androidx.ui.geometry.Offset getOffset();
- field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+ field public static final androidx.ui.graphics.Shadow.Companion Companion;
}
public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
}
public enum StrokeCap {
+ method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeCap[] values();
enum_constant public static final androidx.ui.graphics.StrokeCap butt;
enum_constant public static final androidx.ui.graphics.StrokeCap round;
enum_constant public static final androidx.ui.graphics.StrokeCap square;
}
public enum StrokeJoin {
+ method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeJoin[] values();
enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
enum_constant public static final androidx.ui.graphics.StrokeJoin round;
}
public enum TileMode {
+ method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.TileMode[] values();
enum_constant public static final androidx.ui.graphics.TileMode Clamp;
enum_constant public static final androidx.ui.graphics.TileMode Mirror;
enum_constant public static final androidx.ui.graphics.TileMode Repeated;
}
public enum VertexMode {
+ method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.VertexMode[] values();
enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
package androidx.ui.graphics.colorspace {
public enum Adaptation {
+ method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.Adaptation[] values();
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
public enum ColorModel {
method public final int getComponentCount();
+ method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.ColorModel[] values();
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
property public final androidx.ui.graphics.colorspace.Rgb Srgb;
- field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
}
public class Connector {
@@ -648,10 +676,12 @@
property public final androidx.ui.graphics.colorspace.WhitePoint D65;
property public final androidx.ui.graphics.colorspace.WhitePoint D75;
property public final androidx.ui.graphics.colorspace.WhitePoint E;
- field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
}
public enum RenderIntent {
+ method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
property public final androidx.ui.geometry.Offset center;
property public abstract androidx.ui.core.LayoutDirection layoutDirection;
property public final androidx.ui.geometry.Size size;
- field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
}
public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
}
public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
- field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+ field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
}
public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
method public float getMiter();
method public android.graphics.PathEffect? getPathEffect();
method public float getWidth();
- field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
field public static final float DefaultMiter = 4.0f;
field public static final float HairlineWidth = 0.0f;
}
@@ -865,25 +895,25 @@
public final class PathBuilder {
ctor public PathBuilder();
method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder close();
method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
- method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+ method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
- method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+ method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
}
public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
}
public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
- field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+ field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
}
public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
}
public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeHorizontalTo(float x);
+ ctor public PathNode.RelativeHorizontalTo(float dx);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
- method public float getX();
+ method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+ method public float getDx();
}
public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeLineTo(float x, float y);
+ ctor public PathNode.RelativeLineTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeMoveTo(float x, float y);
+ ctor public PathNode.RelativeMoveTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+ ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeVerticalTo(float y);
+ ctor public PathNode.RelativeVerticalTo(float dy);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+ method public float getDy();
}
public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
method public float[] toFloatArray();
method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
property public final inline java.util.List<java.lang.Float> m3storage;
- field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
}
public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
property public final inline androidx.ui.graphics.vectormath.Vector3 up;
property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
- field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
}
public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
}
public enum MatrixColumn {
+ method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
}
public enum VectorComponent {
+ method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/current.txt b/ui/ui-graphics/api/current.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/current.txt
+++ b/ui/ui-graphics/api/current.txt
@@ -44,14 +44,14 @@
method public android.graphics.Path getInternalPath();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType value);
method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
}
public enum BlendMode {
+ method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.BlendMode[] values();
enum_constant public static final androidx.ui.graphics.BlendMode clear;
enum_constant public static final androidx.ui.graphics.BlendMode color;
enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
}
public enum ClipOp {
+ method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ClipOp[] values();
enum_constant public static final androidx.ui.graphics.ClipOp difference;
enum_constant public static final androidx.ui.graphics.ClipOp intersect;
}
@@ -198,7 +202,7 @@
method public long getValue();
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method public static String toString-impl(long $this);
- field public static final androidx.ui.graphics.Color.Companion! Companion;
+ field public static final androidx.ui.graphics.Color.Companion Companion;
}
public static final class Color.Companion {
@@ -236,7 +240,7 @@
method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
method public androidx.ui.graphics.BlendMode getBlendMode();
method public long getColor();
- field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+ field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
}
public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
}
public enum FilterQuality {
+ method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.FilterQuality[] values();
enum_constant public static final androidx.ui.graphics.FilterQuality high;
enum_constant public static final androidx.ui.graphics.FilterQuality low;
enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
}
public enum ImageAssetConfig {
+ method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ImageAssetConfig[] values();
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
}
public enum PaintingStyle {
+ method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PaintingStyle[] values();
enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
}
@@ -395,21 +405,21 @@
method public androidx.ui.graphics.PathFillType getFillType();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType p);
method public void shift(androidx.ui.geometry.Offset offset);
property public abstract androidx.ui.graphics.PathFillType fillType;
property public abstract boolean isConvex;
property public abstract boolean isEmpty;
- field public static final androidx.ui.graphics.Path.Companion! Companion;
+ field public static final androidx.ui.graphics.Path.Companion Companion;
}
public static final class Path.Companion {
@@ -417,11 +427,15 @@
}
public enum PathFillType {
+ method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathFillType[] values();
enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
}
public enum PathOperation {
+ method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathOperation[] values();
enum_constant public static final androidx.ui.graphics.PathOperation difference;
enum_constant public static final androidx.ui.graphics.PathOperation intersect;
enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
}
public enum PointMode {
+ method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PointMode[] values();
enum_constant public static final androidx.ui.graphics.PointMode lines;
enum_constant public static final androidx.ui.graphics.PointMode points;
enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
method public float getBlurRadius();
method public long getColor();
method public androidx.ui.geometry.Offset getOffset();
- field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+ field public static final androidx.ui.graphics.Shadow.Companion Companion;
}
public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
}
public enum StrokeCap {
+ method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeCap[] values();
enum_constant public static final androidx.ui.graphics.StrokeCap butt;
enum_constant public static final androidx.ui.graphics.StrokeCap round;
enum_constant public static final androidx.ui.graphics.StrokeCap square;
}
public enum StrokeJoin {
+ method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeJoin[] values();
enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
enum_constant public static final androidx.ui.graphics.StrokeJoin round;
}
public enum TileMode {
+ method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.TileMode[] values();
enum_constant public static final androidx.ui.graphics.TileMode Clamp;
enum_constant public static final androidx.ui.graphics.TileMode Mirror;
enum_constant public static final androidx.ui.graphics.TileMode Repeated;
}
public enum VertexMode {
+ method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.VertexMode[] values();
enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
package androidx.ui.graphics.colorspace {
public enum Adaptation {
+ method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.Adaptation[] values();
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
public enum ColorModel {
method public final int getComponentCount();
+ method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.ColorModel[] values();
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
property public final androidx.ui.graphics.colorspace.Rgb Srgb;
- field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
}
public class Connector {
@@ -648,10 +676,12 @@
property public final androidx.ui.graphics.colorspace.WhitePoint D65;
property public final androidx.ui.graphics.colorspace.WhitePoint D75;
property public final androidx.ui.graphics.colorspace.WhitePoint E;
- field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
}
public enum RenderIntent {
+ method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
property public final androidx.ui.geometry.Offset center;
property public abstract androidx.ui.core.LayoutDirection layoutDirection;
property public final androidx.ui.geometry.Size size;
- field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
}
public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
}
public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
- field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+ field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
}
public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
method public float getMiter();
method public android.graphics.PathEffect? getPathEffect();
method public float getWidth();
- field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
field public static final float DefaultMiter = 4.0f;
field public static final float HairlineWidth = 0.0f;
}
@@ -865,25 +895,25 @@
public final class PathBuilder {
ctor public PathBuilder();
method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder close();
method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
- method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+ method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
- method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+ method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
}
public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
}
public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
- field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+ field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
}
public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
}
public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeHorizontalTo(float x);
+ ctor public PathNode.RelativeHorizontalTo(float dx);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
- method public float getX();
+ method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+ method public float getDx();
}
public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeLineTo(float x, float y);
+ ctor public PathNode.RelativeLineTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeMoveTo(float x, float y);
+ ctor public PathNode.RelativeMoveTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+ ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeVerticalTo(float y);
+ ctor public PathNode.RelativeVerticalTo(float dy);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+ method public float getDy();
}
public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
method public float[] toFloatArray();
method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
property public final inline java.util.List<java.lang.Float> m3storage;
- field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
}
public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
property public final inline androidx.ui.graphics.vectormath.Vector3 up;
property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
- field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
}
public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
}
public enum MatrixColumn {
+ method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
}
public enum VectorComponent {
+ method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-graphics/api/public_plus_experimental_0.1.0-dev15.txt
@@ -44,14 +44,14 @@
method public android.graphics.Path getInternalPath();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType value);
method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
}
public enum BlendMode {
+ method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.BlendMode[] values();
enum_constant public static final androidx.ui.graphics.BlendMode clear;
enum_constant public static final androidx.ui.graphics.BlendMode color;
enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
}
public enum ClipOp {
+ method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ClipOp[] values();
enum_constant public static final androidx.ui.graphics.ClipOp difference;
enum_constant public static final androidx.ui.graphics.ClipOp intersect;
}
@@ -198,7 +202,7 @@
method public long getValue();
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method public static String toString-impl(long $this);
- field public static final androidx.ui.graphics.Color.Companion! Companion;
+ field public static final androidx.ui.graphics.Color.Companion Companion;
}
public static final class Color.Companion {
@@ -236,7 +240,7 @@
method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
method public androidx.ui.graphics.BlendMode getBlendMode();
method public long getColor();
- field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+ field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
}
public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
}
public enum FilterQuality {
+ method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.FilterQuality[] values();
enum_constant public static final androidx.ui.graphics.FilterQuality high;
enum_constant public static final androidx.ui.graphics.FilterQuality low;
enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
}
public enum ImageAssetConfig {
+ method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ImageAssetConfig[] values();
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
}
public enum PaintingStyle {
+ method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PaintingStyle[] values();
enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
}
@@ -395,21 +405,21 @@
method public androidx.ui.graphics.PathFillType getFillType();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType p);
method public void shift(androidx.ui.geometry.Offset offset);
property public abstract androidx.ui.graphics.PathFillType fillType;
property public abstract boolean isConvex;
property public abstract boolean isEmpty;
- field public static final androidx.ui.graphics.Path.Companion! Companion;
+ field public static final androidx.ui.graphics.Path.Companion Companion;
}
public static final class Path.Companion {
@@ -417,11 +427,15 @@
}
public enum PathFillType {
+ method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathFillType[] values();
enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
}
public enum PathOperation {
+ method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathOperation[] values();
enum_constant public static final androidx.ui.graphics.PathOperation difference;
enum_constant public static final androidx.ui.graphics.PathOperation intersect;
enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
}
public enum PointMode {
+ method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PointMode[] values();
enum_constant public static final androidx.ui.graphics.PointMode lines;
enum_constant public static final androidx.ui.graphics.PointMode points;
enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
method public float getBlurRadius();
method public long getColor();
method public androidx.ui.geometry.Offset getOffset();
- field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+ field public static final androidx.ui.graphics.Shadow.Companion Companion;
}
public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
}
public enum StrokeCap {
+ method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeCap[] values();
enum_constant public static final androidx.ui.graphics.StrokeCap butt;
enum_constant public static final androidx.ui.graphics.StrokeCap round;
enum_constant public static final androidx.ui.graphics.StrokeCap square;
}
public enum StrokeJoin {
+ method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeJoin[] values();
enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
enum_constant public static final androidx.ui.graphics.StrokeJoin round;
}
public enum TileMode {
+ method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.TileMode[] values();
enum_constant public static final androidx.ui.graphics.TileMode Clamp;
enum_constant public static final androidx.ui.graphics.TileMode Mirror;
enum_constant public static final androidx.ui.graphics.TileMode Repeated;
}
public enum VertexMode {
+ method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.VertexMode[] values();
enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
package androidx.ui.graphics.colorspace {
public enum Adaptation {
+ method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.Adaptation[] values();
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
public enum ColorModel {
method public final int getComponentCount();
+ method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.ColorModel[] values();
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
property public final androidx.ui.graphics.colorspace.Rgb Srgb;
- field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
}
public class Connector {
@@ -648,10 +676,12 @@
property public final androidx.ui.graphics.colorspace.WhitePoint D65;
property public final androidx.ui.graphics.colorspace.WhitePoint D75;
property public final androidx.ui.graphics.colorspace.WhitePoint E;
- field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
}
public enum RenderIntent {
+ method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
property public final androidx.ui.geometry.Offset center;
property public abstract androidx.ui.core.LayoutDirection layoutDirection;
property public final androidx.ui.geometry.Size size;
- field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
}
public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
}
public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
- field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+ field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
}
public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
method public float getMiter();
method public android.graphics.PathEffect? getPathEffect();
method public float getWidth();
- field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
field public static final float DefaultMiter = 4.0f;
field public static final float HairlineWidth = 0.0f;
}
@@ -865,25 +895,25 @@
public final class PathBuilder {
ctor public PathBuilder();
method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder close();
method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
- method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+ method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
- method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+ method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
}
public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
}
public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
- field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+ field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
}
public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
}
public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeHorizontalTo(float x);
+ ctor public PathNode.RelativeHorizontalTo(float dx);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
- method public float getX();
+ method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+ method public float getDx();
}
public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeLineTo(float x, float y);
+ ctor public PathNode.RelativeLineTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeMoveTo(float x, float y);
+ ctor public PathNode.RelativeMoveTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+ ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeVerticalTo(float y);
+ ctor public PathNode.RelativeVerticalTo(float dy);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+ method public float getDy();
}
public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
method public float[] toFloatArray();
method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
property public final inline java.util.List<java.lang.Float> m3storage;
- field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
}
public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
property public final inline androidx.ui.graphics.vectormath.Vector3 up;
property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
- field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
}
public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
}
public enum MatrixColumn {
+ method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
}
public enum VectorComponent {
+ method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/public_plus_experimental_current.txt b/ui/ui-graphics/api/public_plus_experimental_current.txt
index d402782..6ca84af 100644
--- a/ui/ui-graphics/api/public_plus_experimental_current.txt
+++ b/ui/ui-graphics/api/public_plus_experimental_current.txt
@@ -44,14 +44,14 @@
method public android.graphics.Path getInternalPath();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType value);
method public void shift(androidx.ui.geometry.Offset offset);
@@ -78,6 +78,8 @@
}
public enum BlendMode {
+ method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.BlendMode[] values();
enum_constant public static final androidx.ui.graphics.BlendMode clear;
enum_constant public static final androidx.ui.graphics.BlendMode color;
enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -174,6 +176,8 @@
}
public enum ClipOp {
+ method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ClipOp[] values();
enum_constant public static final androidx.ui.graphics.ClipOp difference;
enum_constant public static final androidx.ui.graphics.ClipOp intersect;
}
@@ -198,7 +202,7 @@
method public long getValue();
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method public static String toString-impl(long $this);
- field public static final androidx.ui.graphics.Color.Companion! Companion;
+ field public static final androidx.ui.graphics.Color.Companion Companion;
}
public static final class Color.Companion {
@@ -236,7 +240,7 @@
method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
method public androidx.ui.graphics.BlendMode getBlendMode();
method public long getColor();
- field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+ field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
}
public static final class ColorFilter.Companion {
@@ -258,6 +262,8 @@
}
public enum FilterQuality {
+ method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.FilterQuality[] values();
enum_constant public static final androidx.ui.graphics.FilterQuality high;
enum_constant public static final androidx.ui.graphics.FilterQuality low;
enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -283,6 +289,8 @@
}
public enum ImageAssetConfig {
+ method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ImageAssetConfig[] values();
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -376,6 +384,8 @@
}
public enum PaintingStyle {
+ method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PaintingStyle[] values();
enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
}
@@ -395,21 +405,21 @@
method public androidx.ui.graphics.PathFillType getFillType();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType p);
method public void shift(androidx.ui.geometry.Offset offset);
property public abstract androidx.ui.graphics.PathFillType fillType;
property public abstract boolean isConvex;
property public abstract boolean isEmpty;
- field public static final androidx.ui.graphics.Path.Companion! Companion;
+ field public static final androidx.ui.graphics.Path.Companion Companion;
}
public static final class Path.Companion {
@@ -417,11 +427,15 @@
}
public enum PathFillType {
+ method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathFillType[] values();
enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
}
public enum PathOperation {
+ method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathOperation[] values();
enum_constant public static final androidx.ui.graphics.PathOperation difference;
enum_constant public static final androidx.ui.graphics.PathOperation intersect;
enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -440,6 +454,8 @@
}
public enum PointMode {
+ method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PointMode[] values();
enum_constant public static final androidx.ui.graphics.PointMode lines;
enum_constant public static final androidx.ui.graphics.PointMode points;
enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -482,7 +498,7 @@
method public float getBlurRadius();
method public long getColor();
method public androidx.ui.geometry.Offset getOffset();
- field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+ field public static final androidx.ui.graphics.Shadow.Companion Companion;
}
public static final class Shadow.Companion {
@@ -506,24 +522,32 @@
}
public enum StrokeCap {
+ method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeCap[] values();
enum_constant public static final androidx.ui.graphics.StrokeCap butt;
enum_constant public static final androidx.ui.graphics.StrokeCap round;
enum_constant public static final androidx.ui.graphics.StrokeCap square;
}
public enum StrokeJoin {
+ method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeJoin[] values();
enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
enum_constant public static final androidx.ui.graphics.StrokeJoin round;
}
public enum TileMode {
+ method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.TileMode[] values();
enum_constant public static final androidx.ui.graphics.TileMode Clamp;
enum_constant public static final androidx.ui.graphics.TileMode Mirror;
enum_constant public static final androidx.ui.graphics.TileMode Repeated;
}
public enum VertexMode {
+ method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.VertexMode[] values();
enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -547,6 +571,8 @@
package androidx.ui.graphics.colorspace {
public enum Adaptation {
+ method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.Adaptation[] values();
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -554,6 +580,8 @@
public enum ColorModel {
method public final int getComponentCount();
+ method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.ColorModel[] values();
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -618,7 +646,7 @@
property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
property public final androidx.ui.graphics.colorspace.Rgb Srgb;
- field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
}
public class Connector {
@@ -648,10 +676,12 @@
property public final androidx.ui.graphics.colorspace.WhitePoint D65;
property public final androidx.ui.graphics.colorspace.WhitePoint D75;
property public final androidx.ui.graphics.colorspace.WhitePoint E;
- field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
}
public enum RenderIntent {
+ method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -750,7 +780,7 @@
property public final androidx.ui.geometry.Offset center;
property public abstract androidx.ui.core.LayoutDirection layoutDirection;
property public final androidx.ui.geometry.Size size;
- field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
}
public static final class DrawScope.Companion {
@@ -797,7 +827,7 @@
}
public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
- field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+ field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
}
public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -814,7 +844,7 @@
method public float getMiter();
method public android.graphics.PathEffect? getPathEffect();
method public float getWidth();
- field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
field public static final float DefaultMiter = 4.0f;
field public static final float HairlineWidth = 0.0f;
}
@@ -865,25 +895,25 @@
public final class PathBuilder {
ctor public PathBuilder();
method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder close();
method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
- method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+ method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
- method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+ method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
}
public abstract sealed class PathNode {
@@ -911,7 +941,7 @@
}
public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
- field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+ field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
}
public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1028,70 +1058,70 @@
}
public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeHorizontalTo(float x);
+ ctor public PathNode.RelativeHorizontalTo(float dx);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
- method public float getX();
+ method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+ method public float getDx();
}
public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeLineTo(float x, float y);
+ ctor public PathNode.RelativeLineTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeMoveTo(float x, float y);
+ ctor public PathNode.RelativeMoveTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+ ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeVerticalTo(float y);
+ ctor public PathNode.RelativeVerticalTo(float dy);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+ method public float getDy();
}
public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1149,7 +1179,7 @@
method public float[] toFloatArray();
method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
property public final inline java.util.List<java.lang.Float> m3storage;
- field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
}
public static final class Matrix3.Companion {
@@ -1229,7 +1259,7 @@
property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
property public final inline androidx.ui.graphics.vectormath.Vector3 up;
property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
- field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
}
public static final class Matrix4.Companion {
@@ -1256,6 +1286,8 @@
}
public enum MatrixColumn {
+ method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1544,6 +1576,8 @@
}
public enum VectorComponent {
+ method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/restricted_0.1.0-dev15.txt b/ui/ui-graphics/api/restricted_0.1.0-dev15.txt
index 79ad302..5fc211b 100644
--- a/ui/ui-graphics/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-graphics/api/restricted_0.1.0-dev15.txt
@@ -76,14 +76,14 @@
method public android.graphics.Path getInternalPath();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType value);
method public void shift(androidx.ui.geometry.Offset offset);
@@ -110,6 +110,8 @@
}
public enum BlendMode {
+ method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.BlendMode[] values();
enum_constant public static final androidx.ui.graphics.BlendMode clear;
enum_constant public static final androidx.ui.graphics.BlendMode color;
enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -207,6 +209,8 @@
}
public enum ClipOp {
+ method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ClipOp[] values();
enum_constant public static final androidx.ui.graphics.ClipOp difference;
enum_constant public static final androidx.ui.graphics.ClipOp intersect;
}
@@ -231,7 +235,7 @@
method public long getValue();
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method public static String toString-impl(long $this);
- field public static final androidx.ui.graphics.Color.Companion! Companion;
+ field public static final androidx.ui.graphics.Color.Companion Companion;
}
public static final class Color.Companion {
@@ -269,7 +273,7 @@
method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
method public androidx.ui.graphics.BlendMode getBlendMode();
method public long getColor();
- field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+ field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
}
public static final class ColorFilter.Companion {
@@ -291,6 +295,8 @@
}
public enum FilterQuality {
+ method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.FilterQuality[] values();
enum_constant public static final androidx.ui.graphics.FilterQuality high;
enum_constant public static final androidx.ui.graphics.FilterQuality low;
enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -316,6 +322,8 @@
}
public enum ImageAssetConfig {
+ method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ImageAssetConfig[] values();
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -409,6 +417,8 @@
}
public enum PaintingStyle {
+ method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PaintingStyle[] values();
enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
}
@@ -428,21 +438,21 @@
method public androidx.ui.graphics.PathFillType getFillType();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType p);
method public void shift(androidx.ui.geometry.Offset offset);
property public abstract androidx.ui.graphics.PathFillType fillType;
property public abstract boolean isConvex;
property public abstract boolean isEmpty;
- field public static final androidx.ui.graphics.Path.Companion! Companion;
+ field public static final androidx.ui.graphics.Path.Companion Companion;
}
public static final class Path.Companion {
@@ -450,11 +460,15 @@
}
public enum PathFillType {
+ method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathFillType[] values();
enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
}
public enum PathOperation {
+ method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathOperation[] values();
enum_constant public static final androidx.ui.graphics.PathOperation difference;
enum_constant public static final androidx.ui.graphics.PathOperation intersect;
enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -473,6 +487,8 @@
}
public enum PointMode {
+ method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PointMode[] values();
enum_constant public static final androidx.ui.graphics.PointMode lines;
enum_constant public static final androidx.ui.graphics.PointMode points;
enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -515,7 +531,7 @@
method public float getBlurRadius();
method public long getColor();
method public androidx.ui.geometry.Offset getOffset();
- field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+ field public static final androidx.ui.graphics.Shadow.Companion Companion;
}
public static final class Shadow.Companion {
@@ -539,24 +555,32 @@
}
public enum StrokeCap {
+ method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeCap[] values();
enum_constant public static final androidx.ui.graphics.StrokeCap butt;
enum_constant public static final androidx.ui.graphics.StrokeCap round;
enum_constant public static final androidx.ui.graphics.StrokeCap square;
}
public enum StrokeJoin {
+ method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeJoin[] values();
enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
enum_constant public static final androidx.ui.graphics.StrokeJoin round;
}
public enum TileMode {
+ method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.TileMode[] values();
enum_constant public static final androidx.ui.graphics.TileMode Clamp;
enum_constant public static final androidx.ui.graphics.TileMode Mirror;
enum_constant public static final androidx.ui.graphics.TileMode Repeated;
}
public enum VertexMode {
+ method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.VertexMode[] values();
enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -580,6 +604,8 @@
package androidx.ui.graphics.colorspace {
public enum Adaptation {
+ method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.Adaptation[] values();
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -587,6 +613,8 @@
public enum ColorModel {
method public final int getComponentCount();
+ method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.ColorModel[] values();
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -651,7 +679,7 @@
property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
property public final androidx.ui.graphics.colorspace.Rgb Srgb;
- field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
}
public class Connector {
@@ -681,10 +709,12 @@
property public final androidx.ui.graphics.colorspace.WhitePoint D65;
property public final androidx.ui.graphics.colorspace.WhitePoint D75;
property public final androidx.ui.graphics.colorspace.WhitePoint E;
- field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
}
public enum RenderIntent {
+ method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -784,7 +814,7 @@
property public final androidx.ui.geometry.Offset center;
property public abstract androidx.ui.core.LayoutDirection layoutDirection;
property public final androidx.ui.geometry.Size size;
- field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
field @kotlin.PublishedApi internal androidx.ui.graphics.Canvas canvas;
field @kotlin.PublishedApi internal final androidx.ui.graphics.drawscope.DrawTransform transform;
}
@@ -833,7 +863,7 @@
}
public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
- field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+ field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
}
public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -850,7 +880,7 @@
method public float getMiter();
method public android.graphics.PathEffect? getPathEffect();
method public float getWidth();
- field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
field public static final float DefaultMiter = 4.0f;
field public static final float HairlineWidth = 0.0f;
}
@@ -901,25 +931,25 @@
public final class PathBuilder {
ctor public PathBuilder();
method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder close();
method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
- method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+ method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
- method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+ method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
}
public abstract sealed class PathNode {
@@ -947,7 +977,7 @@
}
public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
- field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+ field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
}
public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1064,70 +1094,70 @@
}
public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeHorizontalTo(float x);
+ ctor public PathNode.RelativeHorizontalTo(float dx);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
- method public float getX();
+ method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+ method public float getDx();
}
public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeLineTo(float x, float y);
+ ctor public PathNode.RelativeLineTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeMoveTo(float x, float y);
+ ctor public PathNode.RelativeMoveTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+ ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeVerticalTo(float y);
+ ctor public PathNode.RelativeVerticalTo(float dy);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+ method public float getDy();
}
public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1185,7 +1215,7 @@
method public float[] toFloatArray();
method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
property public final inline java.util.List<java.lang.Float> m3storage;
- field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
}
public static final class Matrix3.Companion {
@@ -1265,7 +1295,7 @@
property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
property public final inline androidx.ui.graphics.vectormath.Vector3 up;
property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
- field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
}
public static final class Matrix4.Companion {
@@ -1292,6 +1322,8 @@
}
public enum MatrixColumn {
+ method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1580,6 +1612,8 @@
}
public enum VectorComponent {
+ method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/api/restricted_current.txt b/ui/ui-graphics/api/restricted_current.txt
index 79ad302..5fc211b 100644
--- a/ui/ui-graphics/api/restricted_current.txt
+++ b/ui/ui-graphics/api/restricted_current.txt
@@ -76,14 +76,14 @@
method public android.graphics.Path getInternalPath();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType value);
method public void shift(androidx.ui.geometry.Offset offset);
@@ -110,6 +110,8 @@
}
public enum BlendMode {
+ method public static androidx.ui.graphics.BlendMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.BlendMode[] values();
enum_constant public static final androidx.ui.graphics.BlendMode clear;
enum_constant public static final androidx.ui.graphics.BlendMode color;
enum_constant public static final androidx.ui.graphics.BlendMode colorBurn;
@@ -207,6 +209,8 @@
}
public enum ClipOp {
+ method public static androidx.ui.graphics.ClipOp valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ClipOp[] values();
enum_constant public static final androidx.ui.graphics.ClipOp difference;
enum_constant public static final androidx.ui.graphics.ClipOp intersect;
}
@@ -231,7 +235,7 @@
method public long getValue();
method @androidx.compose.Immutable public static inline int hashCode-impl(long p);
method public static String toString-impl(long $this);
- field public static final androidx.ui.graphics.Color.Companion! Companion;
+ field public static final androidx.ui.graphics.Color.Companion Companion;
}
public static final class Color.Companion {
@@ -269,7 +273,7 @@
method @androidx.compose.Immutable public androidx.ui.graphics.ColorFilter copy-vOa7YyA(long color, androidx.ui.graphics.BlendMode blendMode);
method public androidx.ui.graphics.BlendMode getBlendMode();
method public long getColor();
- field public static final androidx.ui.graphics.ColorFilter.Companion! Companion;
+ field public static final androidx.ui.graphics.ColorFilter.Companion Companion;
}
public static final class ColorFilter.Companion {
@@ -291,6 +295,8 @@
}
public enum FilterQuality {
+ method public static androidx.ui.graphics.FilterQuality valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.FilterQuality[] values();
enum_constant public static final androidx.ui.graphics.FilterQuality high;
enum_constant public static final androidx.ui.graphics.FilterQuality low;
enum_constant public static final androidx.ui.graphics.FilterQuality medium;
@@ -316,6 +322,8 @@
}
public enum ImageAssetConfig {
+ method public static androidx.ui.graphics.ImageAssetConfig valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.ImageAssetConfig[] values();
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Alpha8;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig Argb8888;
enum_constant public static final androidx.ui.graphics.ImageAssetConfig F16;
@@ -409,6 +417,8 @@
}
public enum PaintingStyle {
+ method public static androidx.ui.graphics.PaintingStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PaintingStyle[] values();
enum_constant public static final androidx.ui.graphics.PaintingStyle fill;
enum_constant public static final androidx.ui.graphics.PaintingStyle stroke;
}
@@ -428,21 +438,21 @@
method public androidx.ui.graphics.PathFillType getFillType();
method public boolean isConvex();
method public boolean isEmpty();
- method public void lineTo(float dx, float dy);
- method public void moveTo(float dx, float dy);
+ method public void lineTo(float x, float y);
+ method public void moveTo(float x, float y);
method public boolean op(androidx.ui.graphics.Path path1, androidx.ui.graphics.Path path2, androidx.ui.graphics.PathOperation operation);
method public void quadraticBezierTo(float x1, float y1, float x2, float y2);
- method public void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3);
+ method public void relativeCubicTo(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public void relativeLineTo(float dx, float dy);
method public void relativeMoveTo(float dx, float dy);
- method public void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2);
+ method public void relativeQuadraticBezierTo(float dx1, float dy1, float dx2, float dy2);
method public void reset();
method public void setFillType(androidx.ui.graphics.PathFillType p);
method public void shift(androidx.ui.geometry.Offset offset);
property public abstract androidx.ui.graphics.PathFillType fillType;
property public abstract boolean isConvex;
property public abstract boolean isEmpty;
- field public static final androidx.ui.graphics.Path.Companion! Companion;
+ field public static final androidx.ui.graphics.Path.Companion Companion;
}
public static final class Path.Companion {
@@ -450,11 +460,15 @@
}
public enum PathFillType {
+ method public static androidx.ui.graphics.PathFillType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathFillType[] values();
enum_constant public static final androidx.ui.graphics.PathFillType evenOdd;
enum_constant public static final androidx.ui.graphics.PathFillType nonZero;
}
public enum PathOperation {
+ method public static androidx.ui.graphics.PathOperation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PathOperation[] values();
enum_constant public static final androidx.ui.graphics.PathOperation difference;
enum_constant public static final androidx.ui.graphics.PathOperation intersect;
enum_constant public static final androidx.ui.graphics.PathOperation reverseDifference;
@@ -473,6 +487,8 @@
}
public enum PointMode {
+ method public static androidx.ui.graphics.PointMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.PointMode[] values();
enum_constant public static final androidx.ui.graphics.PointMode lines;
enum_constant public static final androidx.ui.graphics.PointMode points;
enum_constant public static final androidx.ui.graphics.PointMode polygon;
@@ -515,7 +531,7 @@
method public float getBlurRadius();
method public long getColor();
method public androidx.ui.geometry.Offset getOffset();
- field public static final androidx.ui.graphics.Shadow.Companion! Companion;
+ field public static final androidx.ui.graphics.Shadow.Companion Companion;
}
public static final class Shadow.Companion {
@@ -539,24 +555,32 @@
}
public enum StrokeCap {
+ method public static androidx.ui.graphics.StrokeCap valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeCap[] values();
enum_constant public static final androidx.ui.graphics.StrokeCap butt;
enum_constant public static final androidx.ui.graphics.StrokeCap round;
enum_constant public static final androidx.ui.graphics.StrokeCap square;
}
public enum StrokeJoin {
+ method public static androidx.ui.graphics.StrokeJoin valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.StrokeJoin[] values();
enum_constant public static final androidx.ui.graphics.StrokeJoin bevel;
enum_constant public static final androidx.ui.graphics.StrokeJoin miter;
enum_constant public static final androidx.ui.graphics.StrokeJoin round;
}
public enum TileMode {
+ method public static androidx.ui.graphics.TileMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.TileMode[] values();
enum_constant public static final androidx.ui.graphics.TileMode Clamp;
enum_constant public static final androidx.ui.graphics.TileMode Mirror;
enum_constant public static final androidx.ui.graphics.TileMode Repeated;
}
public enum VertexMode {
+ method public static androidx.ui.graphics.VertexMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.VertexMode[] values();
enum_constant public static final androidx.ui.graphics.VertexMode triangleFan;
enum_constant public static final androidx.ui.graphics.VertexMode triangleStrip;
enum_constant public static final androidx.ui.graphics.VertexMode triangles;
@@ -580,6 +604,8 @@
package androidx.ui.graphics.colorspace {
public enum Adaptation {
+ method public static androidx.ui.graphics.colorspace.Adaptation valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.Adaptation[] values();
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Bradford;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation Ciecat02;
enum_constant public static final androidx.ui.graphics.colorspace.Adaptation VonKries;
@@ -587,6 +613,8 @@
public enum ColorModel {
method public final int getComponentCount();
+ method public static androidx.ui.graphics.colorspace.ColorModel valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.ColorModel[] values();
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Cmyk;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Lab;
enum_constant public static final androidx.ui.graphics.colorspace.ColorModel Rgb;
@@ -651,7 +679,7 @@
property public final androidx.ui.graphics.colorspace.Rgb ProPhotoRgb;
property public final androidx.ui.graphics.colorspace.Rgb SmpteC;
property public final androidx.ui.graphics.colorspace.Rgb Srgb;
- field public static final androidx.ui.graphics.colorspace.ColorSpaces! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.ColorSpaces INSTANCE;
}
public class Connector {
@@ -681,10 +709,12 @@
property public final androidx.ui.graphics.colorspace.WhitePoint D65;
property public final androidx.ui.graphics.colorspace.WhitePoint D75;
property public final androidx.ui.graphics.colorspace.WhitePoint E;
- field public static final androidx.ui.graphics.colorspace.Illuminant! INSTANCE;
+ field public static final androidx.ui.graphics.colorspace.Illuminant INSTANCE;
}
public enum RenderIntent {
+ method public static androidx.ui.graphics.colorspace.RenderIntent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.colorspace.RenderIntent[] values();
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Absolute;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Perceptual;
enum_constant public static final androidx.ui.graphics.colorspace.RenderIntent Relative;
@@ -784,7 +814,7 @@
property public final androidx.ui.geometry.Offset center;
property public abstract androidx.ui.core.LayoutDirection layoutDirection;
property public final androidx.ui.geometry.Size size;
- field public static final androidx.ui.graphics.drawscope.DrawScope.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.DrawScope.Companion Companion;
field @kotlin.PublishedApi internal androidx.ui.graphics.Canvas canvas;
field @kotlin.PublishedApi internal final androidx.ui.graphics.drawscope.DrawTransform transform;
}
@@ -833,7 +863,7 @@
}
public final class Fill extends androidx.ui.graphics.drawscope.DrawStyle {
- field public static final androidx.ui.graphics.drawscope.Fill! INSTANCE;
+ field public static final androidx.ui.graphics.drawscope.Fill INSTANCE;
}
public final class Stroke extends androidx.ui.graphics.drawscope.DrawStyle {
@@ -850,7 +880,7 @@
method public float getMiter();
method public android.graphics.PathEffect? getPathEffect();
method public float getWidth();
- field public static final androidx.ui.graphics.drawscope.Stroke.Companion! Companion;
+ field public static final androidx.ui.graphics.drawscope.Stroke.Companion Companion;
field public static final float DefaultMiter = 4.0f;
field public static final float HairlineWidth = 0.0f;
}
@@ -901,25 +931,25 @@
public final class PathBuilder {
ctor public PathBuilder();
method public androidx.ui.graphics.vector.PathBuilder arcTo(float horizontalEllipseRadius, float verticalEllipseRadius, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder arcToRelative(float a, float b, float theta, boolean isMoreThanHalf, boolean isPositiveArc, float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder close();
method public androidx.ui.graphics.vector.PathBuilder curveTo(float x1, float y1, float x2, float y2, float x3, float y3);
method public androidx.ui.graphics.vector.PathBuilder curveToRelative(float dx1, float dy1, float dx2, float dy2, float dx3, float dy3);
method public java.util.List<androidx.ui.graphics.vector.PathNode> getNodes();
method public androidx.ui.graphics.vector.PathBuilder horizontalLineTo(float x);
- method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float x);
+ method public androidx.ui.graphics.vector.PathBuilder horizontalLineToRelative(float dx);
method public androidx.ui.graphics.vector.PathBuilder lineTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder lineToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder moveTo(float x, float y);
- method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float x, float y);
+ method public androidx.ui.graphics.vector.PathBuilder moveToRelative(float dx, float dy);
method public androidx.ui.graphics.vector.PathBuilder quadTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder quadToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveTo(float x1, float y1, float x2, float y2);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float x1, float y1, float x2, float y2);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveCurveToRelative(float dx1, float dy1, float dx2, float dy2);
method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadTo(float x1, float y1);
- method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float x1, float y1);
+ method public androidx.ui.graphics.vector.PathBuilder reflectiveQuadToRelative(float dx1, float dy1);
method public androidx.ui.graphics.vector.PathBuilder verticalLineTo(float y);
- method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float y);
+ method public androidx.ui.graphics.vector.PathBuilder verticalLineToRelative(float dy);
}
public abstract sealed class PathNode {
@@ -947,7 +977,7 @@
}
public static final class PathNode.Close extends androidx.ui.graphics.vector.PathNode {
- field public static final androidx.ui.graphics.vector.PathNode.Close! INSTANCE;
+ field public static final androidx.ui.graphics.vector.PathNode.Close INSTANCE;
}
public static final class PathNode.CurveTo extends androidx.ui.graphics.vector.PathNode {
@@ -1064,70 +1094,70 @@
}
public static final class PathNode.RelativeHorizontalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeHorizontalTo(float x);
+ ctor public PathNode.RelativeHorizontalTo(float dx);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float x);
- method public float getX();
+ method public androidx.ui.graphics.vector.PathNode.RelativeHorizontalTo copy(float dx);
+ method public float getDx();
}
public static final class PathNode.RelativeLineTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeLineTo(float x, float y);
+ ctor public PathNode.RelativeLineTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeLineTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeMoveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeMoveTo(float x, float y);
+ ctor public PathNode.RelativeMoveTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeMoveTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeQuadTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeQuadTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeQuadTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveCurveTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveCurveTo(float x1, float y1, float x2, float y2);
+ ctor public PathNode.RelativeReflectiveCurveTo(float dx1, float dy1, float dx2, float dy2);
method public float component1();
method public float component2();
method public float component3();
method public float component4();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float x1, float y1, float x2, float y2);
- method public float getX1();
- method public float getX2();
- method public float getY1();
- method public float getY2();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveCurveTo copy(float dx1, float dy1, float dx2, float dy2);
+ method public float getDx1();
+ method public float getDx2();
+ method public float getDy1();
+ method public float getDy2();
}
public static final class PathNode.RelativeReflectiveQuadTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeReflectiveQuadTo(float x, float y);
+ ctor public PathNode.RelativeReflectiveQuadTo(float dx, float dy);
method public float component1();
method public float component2();
- method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float x, float y);
- method public float getX();
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeReflectiveQuadTo copy(float dx, float dy);
+ method public float getDx();
+ method public float getDy();
}
public static final class PathNode.RelativeVerticalTo extends androidx.ui.graphics.vector.PathNode {
- ctor public PathNode.RelativeVerticalTo(float y);
+ ctor public PathNode.RelativeVerticalTo(float dy);
method public float component1();
- method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float y);
- method public float getY();
+ method public androidx.ui.graphics.vector.PathNode.RelativeVerticalTo copy(float dy);
+ method public float getDy();
}
public static final class PathNode.VerticalTo extends androidx.ui.graphics.vector.PathNode {
@@ -1185,7 +1215,7 @@
method public float[] toFloatArray();
method public operator androidx.ui.graphics.vectormath.Matrix3 unaryMinus();
property public final inline java.util.List<java.lang.Float> m3storage;
- field public static final androidx.ui.graphics.vectormath.Matrix3.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix3.Companion Companion;
}
public static final class Matrix3.Companion {
@@ -1265,7 +1295,7 @@
property public final inline androidx.ui.graphics.vectormath.Vector3 translation;
property public final inline androidx.ui.graphics.vectormath.Vector3 up;
property public final inline androidx.ui.graphics.vectormath.Matrix3 upperLeft;
- field public static final androidx.ui.graphics.vectormath.Matrix4.Companion! Companion;
+ field public static final androidx.ui.graphics.vectormath.Matrix4.Companion Companion;
}
public static final class Matrix4.Companion {
@@ -1292,6 +1322,8 @@
}
public enum MatrixColumn {
+ method public static androidx.ui.graphics.vectormath.MatrixColumn valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.MatrixColumn[] values();
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn W;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn X;
enum_constant public static final androidx.ui.graphics.vectormath.MatrixColumn Y;
@@ -1580,6 +1612,8 @@
}
public enum VectorComponent {
+ method public static androidx.ui.graphics.vectormath.VectorComponent valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.graphics.vectormath.VectorComponent[] values();
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent A;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent B;
enum_constant public static final androidx.ui.graphics.vectormath.VectorComponent G;
diff --git a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt
index 6f48e17..e199923 100644
--- a/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt
+++ b/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/ui/graphics/drawscope/DrawScopeTest.kt
@@ -24,7 +24,9 @@
import androidx.ui.graphics.Color
import androidx.ui.graphics.ImageAsset
import androidx.ui.graphics.Paint
+import androidx.ui.graphics.PointMode
import androidx.ui.graphics.SolidColor
+import androidx.ui.graphics.StrokeCap
import androidx.ui.graphics.compositeOver
import androidx.ui.graphics.toPixelMap
import org.junit.Assert.assertEquals
@@ -593,6 +595,160 @@
}
}
+ @Test
+ fun testDrawLineStrokeParametersAreApplied() {
+ val width = 200
+ val height = 200
+ val start = Offset.Zero
+ val end = Offset(width.toFloat(), height.toFloat())
+ val strokeWidth = 10.0f
+ // Test that colors are rendered with the correct stroke parameters
+ testDrawScopeAndCanvasAreEquivalent(
+ width,
+ height,
+ {
+ drawLine(
+ Color.Cyan,
+ start,
+ end,
+ strokeWidth,
+ StrokeCap.round
+ )
+ },
+ { canvas ->
+ canvas.drawLine(start, end, Paint().apply {
+ this.color = Color.Cyan
+ this.strokeWidth = strokeWidth
+ this.strokeCap = StrokeCap.round
+ })
+ }
+ )
+
+ // ... now test that Brush parameters are also rendered with the correct stroke parameters
+ testDrawScopeAndCanvasAreEquivalent(
+ width,
+ height,
+ {
+ drawLine(
+ SolidColor(Color.Cyan),
+ start,
+ end,
+ strokeWidth,
+ StrokeCap.round
+ )
+ },
+ { canvas ->
+ canvas.drawLine(start, end, Paint().apply {
+ this.color = Color.Cyan
+ this.strokeWidth = strokeWidth
+ this.strokeCap = StrokeCap.round
+ })
+ }
+ )
+ }
+
+ @Test
+ fun testDrawPointStrokeParametersAreApplied() {
+ val width = 200
+ val height = 200
+ val points = listOf(
+ Offset.Zero,
+ Offset(10f, 10f),
+ Offset(25f, 25f),
+ Offset(40f, 40f),
+ Offset(50f, 50f),
+ Offset(75f, 75f),
+ Offset(150f, 150f)
+ )
+ // Test first that colors are rendered with the correct stroke parameters
+ testDrawScopeAndCanvasAreEquivalent(
+ width,
+ height,
+ {
+ drawPoints(
+ points,
+ PointMode.points,
+ Color.Magenta,
+ strokeWidth = 15.0f,
+ cap = StrokeCap.butt
+ )
+ },
+ { canvas ->
+ canvas.drawPoints(
+ PointMode.points,
+ points,
+ Paint().apply {
+ this.color = Color.Magenta
+ this.strokeWidth = 15.0f
+ this.strokeCap = StrokeCap.butt
+ }
+ )
+ }
+ )
+
+ // ... now verify that Brush parameters are also rendered with the correct stroke parameters
+ testDrawScopeAndCanvasAreEquivalent(
+ width,
+ height,
+ {
+ drawPoints(
+ points,
+ PointMode.points,
+ SolidColor(Color.Magenta),
+ strokeWidth = 15.0f,
+ cap = StrokeCap.butt
+ )
+ },
+ { canvas ->
+ canvas.drawPoints(
+ PointMode.points,
+ points,
+ Paint().apply {
+ this.color = Color.Magenta
+ this.strokeWidth = 15.0f
+ this.strokeCap = StrokeCap.butt
+ }
+ )
+ }
+ )
+ }
+
+ /**
+ * Helper method used to confirm both DrawScope rendered content and Canvas drawn
+ * content are identical
+ */
+ private fun testDrawScopeAndCanvasAreEquivalent(
+ width: Int,
+ height: Int,
+ drawScopeBlock: DrawScope.() -> Unit,
+ canvasBlock: (Canvas) -> Unit
+ ) {
+ val size = Size(width.toFloat(), height.toFloat())
+ val imageAsset1 = ImageAsset(width, height)
+ TestDrawScope().drawInto(Canvas(imageAsset1), size) {
+ drawScopeBlock()
+ }
+
+ val imageAsset2 = ImageAsset(width, height)
+ canvasBlock(Canvas(imageAsset2))
+
+ val pixelMap1 = imageAsset1.toPixelMap()
+ val pixelMap2 = imageAsset2.toPixelMap()
+ assertEquals(pixelMap1.width, pixelMap2.width)
+ assertEquals(pixelMap1.height, pixelMap2.height)
+ assertEquals(pixelMap1.stride, pixelMap2.stride)
+ assertEquals(pixelMap1.bufferOffset, pixelMap2.bufferOffset)
+ for (x in 0 until pixelMap1.width) {
+ for (y in 0 until pixelMap1.height) {
+ assertEquals("coordinate: " + x + ", " + y + " expected: " +
+ pixelMap1[x, y] + " actual: " + pixelMap2[x, y],
+ pixelMap1[x, y],
+ pixelMap2[x, y]
+ )
+ }
+ }
+ }
+
class SaveCountCanvas(val canvas: Canvas) : Canvas by canvas {
var saveCount: Int = 0
diff --git a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt
index ab68b9c..c6419d9 100644
--- a/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt
+++ b/ui/ui-graphics/src/androidMain/kotlin/androidx/ui/graphics/AndroidPath.kt
@@ -21,7 +21,6 @@
import androidx.ui.geometry.RRect
import androidx.ui.geometry.Rect
import androidx.ui.graphics.vectormath.degrees
-import java.lang.UnsupportedOperationException
actual fun Path(): Path = AndroidPath()
@@ -70,16 +69,16 @@
}
}
- override fun moveTo(dx: Float, dy: Float) {
- internalPath.moveTo(dx, dy)
+ override fun moveTo(x: Float, y: Float) {
+ internalPath.moveTo(x, y)
}
override fun relativeMoveTo(dx: Float, dy: Float) {
internalPath.rMoveTo(dx, dy)
}
- override fun lineTo(dx: Float, dy: Float) {
- internalPath.lineTo(dx, dy)
+ override fun lineTo(x: Float, y: Float) {
+ internalPath.lineTo(x, y)
}
override fun relativeLineTo(dx: Float, dy: Float) {
@@ -90,8 +89,8 @@
internalPath.quadTo(x1, y1, x2, y2)
}
- override fun relativeQuadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float) {
- internalPath.rQuadTo(x1, y1, x2, y2)
+ override fun relativeQuadraticBezierTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float) {
+ internalPath.rQuadTo(dx1, dy1, dx2, dy2)
}
override fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
@@ -102,11 +101,18 @@
)
}
- override fun relativeCubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float) {
+ override fun relativeCubicTo(
+ dx1: Float,
+ dy1: Float,
+ dx2: Float,
+ dy2: Float,
+ dx3: Float,
+ dy3: Float
+ ) {
internalPath.rCubicTo(
- x1, y1,
- x2, y2,
- x3, y3
+ dx1, dy1,
+ dx2, dy2,
+ dx3, dy3
)
}
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt
index cac643c..03a6827 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/Path.kt
@@ -55,7 +55,7 @@
/**
* Starts a new subpath at the given coordinate
*/
- fun moveTo(dx: Float, dy: Float)
+ fun moveTo(x: Float, y: Float)
/**
* Starts a new subpath at the given offset from the current point
@@ -65,7 +65,7 @@
/**
* Adds a straight line segment from the current point to the given point
*/
- fun lineTo(dx: Float, dy: Float)
+ fun lineTo(x: Float, y: Float)
/**
* Adds a straight line segment from the current point to the point
@@ -75,33 +75,33 @@
/**
* Adds a quadratic bezier segment that curves from the current
- * point to the given point (x2,y2), using the control point
- * (x1,y1).
+ * point to the given point ([x2], [y2]), using the control point
+ * ([x1], [y1]).
*/
fun quadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float)
/**
* Adds a quadratic bezier segment that curves from the current
- * point to the point at the offset (x2,y2) from the current point,
- * using the control point at the offset (x1,y1) from the current
+ * point to the point at the offset ([dx2], [dy2]) from the current point,
+ * using the control point at the offset ([dx1], [dy1]) from the current
* point.
*/
- fun relativeQuadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float)
+ fun relativeQuadraticBezierTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float)
/**
* Adds a cubic bezier segment that curves from the current point
- * to the given point (x3,y3), using the control points (x1,y1) and
- * (x2,y2).
+ * to the given point ([x3], [y3]), using the control points ([x1], [y1]) and
+ * ([x2], [y2]).
*/
fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)
/**
* Adds a cubic bezier segment that curves from the current point
- * to the point at the offset (x3,y3) from the current point, using
- * the control points at the offsets (x1,y1) and (x2,y2) from the
+ * to the point at the offset ([dx3], [dy3]) from the current point, using
+ * the control points at the offsets ([dx1], [dy1]) and ([dx2], [dy2]) from the
* current point.
*/
- fun relativeCubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)
+ fun relativeCubicTo(dx1: Float, dy1: Float, dx2: Float, dy2: Float, dx3: Float, dy3: Float)
/**
* If the [forceMoveTo] argument is false, adds a straight line
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt
index 7211201..4047908 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/drawscope/DrawScope.kt
@@ -1078,8 +1078,8 @@
if (this.blendMode != blendMode) this.blendMode = blendMode
if (this.strokeWidth != strokeWidth) this.strokeWidth = strokeWidth
if (this.strokeMiterLimit != miter) this.strokeMiterLimit = miter
- if (this.strokeCap != strokeCap) this.strokeCap = cap
- if (this.strokeJoin != strokeJoin) this.strokeJoin = join
+ if (this.strokeCap != cap) this.strokeCap = cap
+ if (this.strokeJoin != join) this.strokeJoin = join
this.asFrameworkPaint().setNativePathEffect(pathEffect)
}
@@ -1103,8 +1103,8 @@
if (this.blendMode != blendMode) this.blendMode = blendMode
if (this.strokeWidth != strokeWidth) this.strokeWidth = strokeWidth
if (this.strokeMiterLimit != miter) this.strokeMiterLimit = miter
- if (this.strokeCap != strokeCap) this.strokeCap = cap
- if (this.strokeJoin != strokeJoin) this.strokeJoin = join
+ if (this.strokeCap != cap) this.strokeCap = cap
+ if (this.strokeJoin != join) this.strokeJoin = join
this.asFrameworkPaint().setNativePathEffect(pathEffect)
}
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt
index 96c514a..031c47c 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathBuilder.kt
@@ -26,19 +26,19 @@
fun moveTo(x: Float, y: Float) = addNode(PathNode.MoveTo(x, y))
- fun moveToRelative(x: Float, y: Float) = addNode(PathNode.RelativeMoveTo(x, y))
+ fun moveToRelative(dx: Float, dy: Float) = addNode(PathNode.RelativeMoveTo(dx, dy))
fun lineTo(x: Float, y: Float) = addNode(PathNode.LineTo(x, y))
- fun lineToRelative(x: Float, y: Float) = addNode(PathNode.RelativeLineTo(x, y))
+ fun lineToRelative(dx: Float, dy: Float) = addNode(PathNode.RelativeLineTo(dx, dy))
fun horizontalLineTo(x: Float) = addNode(PathNode.HorizontalTo(x))
- fun horizontalLineToRelative(x: Float) = addNode(PathNode.RelativeHorizontalTo(x))
+ fun horizontalLineToRelative(dx: Float) = addNode(PathNode.RelativeHorizontalTo(dx))
fun verticalLineTo(y: Float) = addNode(PathNode.VerticalTo(y))
- fun verticalLineToRelative(y: Float) = addNode(PathNode.RelativeVerticalTo(y))
+ fun verticalLineToRelative(dy: Float) = addNode(PathNode.RelativeVerticalTo(dy))
fun curveTo(
x1: Float,
@@ -61,20 +61,20 @@
fun reflectiveCurveTo(x1: Float, y1: Float, x2: Float, y2: Float) =
addNode(PathNode.ReflectiveCurveTo(x1, y1, x2, y2))
- fun reflectiveCurveToRelative(x1: Float, y1: Float, x2: Float, y2: Float) =
- addNode(PathNode.RelativeReflectiveCurveTo(x1, y1, x2, y2))
+ fun reflectiveCurveToRelative(dx1: Float, dy1: Float, dx2: Float, dy2: Float) =
+ addNode(PathNode.RelativeReflectiveCurveTo(dx1, dy1, dx2, dy2))
fun quadTo(x1: Float, y1: Float, x2: Float, y2: Float) =
addNode(PathNode.QuadTo(x1, y1, x2, y2))
- fun quadToRelative(x1: Float, y1: Float, x2: Float, y2: Float) =
- addNode(PathNode.RelativeQuadTo(x1, y1, x2, y2))
+ fun quadToRelative(dx1: Float, dy1: Float, dx2: Float, dy2: Float) =
+ addNode(PathNode.RelativeQuadTo(dx1, dy1, dx2, dy2))
fun reflectiveQuadTo(x1: Float, y1: Float) =
addNode(PathNode.ReflectiveQuadTo(x1, y1))
- fun reflectiveQuadToRelative(x1: Float, y1: Float) =
- addNode(PathNode.RelativeReflectiveQuadTo(x1, y1))
+ fun reflectiveQuadToRelative(dx1: Float, dy1: Float) =
+ addNode(PathNode.RelativeReflectiveQuadTo(dx1, dy1))
fun arcTo(
horizontalEllipseRadius: Float,
@@ -102,9 +102,9 @@
theta: Float,
isMoreThanHalf: Boolean,
isPositiveArc: Boolean,
- x1: Float,
- y1: Float
- ) = addNode(PathNode.RelativeArcTo(a, b, theta, isMoreThanHalf, isPositiveArc, x1, y1))
+ dx1: Float,
+ dy1: Float
+ ) = addNode(PathNode.RelativeArcTo(a, b, theta, isMoreThanHalf, isPositiveArc, dx1, dy1))
private fun addNode(node: PathNode): PathBuilder {
nodes.add(node)
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt
index e2bb858..319b14f 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathNode.kt
@@ -27,16 +27,16 @@
// for simplicity and to make equals comparisons robust.
object Close : PathNode()
- data class RelativeMoveTo(val x: Float, val y: Float) : PathNode()
+ data class RelativeMoveTo(val dx: Float, val dy: Float) : PathNode()
data class MoveTo(val x: Float, val y: Float) : PathNode()
- data class RelativeLineTo(val x: Float, val y: Float) : PathNode()
+ data class RelativeLineTo(val dx: Float, val dy: Float) : PathNode()
data class LineTo(val x: Float, val y: Float) : PathNode()
- data class RelativeHorizontalTo(val x: Float) : PathNode()
+ data class RelativeHorizontalTo(val dx: Float) : PathNode()
data class HorizontalTo(val x: Float) : PathNode()
- data class RelativeVerticalTo(val y: Float) : PathNode()
+ data class RelativeVerticalTo(val dy: Float) : PathNode()
data class VerticalTo(val y: Float) : PathNode()
data class RelativeCurveTo(
@@ -58,10 +58,10 @@
) : PathNode(isCurve = true)
data class RelativeReflectiveCurveTo(
- val x1: Float,
- val y1: Float,
- val x2: Float,
- val y2: Float
+ val dx1: Float,
+ val dy1: Float,
+ val dx2: Float,
+ val dy2: Float
) : PathNode(isCurve = true)
data class ReflectiveCurveTo(
@@ -72,10 +72,10 @@
) : PathNode(isCurve = true)
data class RelativeQuadTo(
- val x1: Float,
- val y1: Float,
- val x2: Float,
- val y2: Float
+ val dx1: Float,
+ val dy1: Float,
+ val dx2: Float,
+ val dy2: Float
) : PathNode(isQuad = true)
data class QuadTo(
@@ -86,8 +86,8 @@
) : PathNode(isQuad = true)
data class RelativeReflectiveQuadTo(
- val x: Float,
- val y: Float
+ val dx: Float,
+ val dy: Float
) : PathNode(isQuad = true)
data class ReflectiveQuadTo(
@@ -125,7 +125,7 @@
internal fun Char.toPathNodes(args: FloatArray): List<PathNode> = when (this) {
RelativeCloseKey, CloseKey -> listOf(PathNode.Close)
RelativeMoveToKey -> pathNodesFromArgs(args, NUM_MOVE_TO_ARGS) { array ->
- PathNode.RelativeMoveTo(x = array[0], y = array[1])
+ PathNode.RelativeMoveTo(dx = array[0], dy = array[1])
}
MoveToKey -> pathNodesFromArgs(args, NUM_MOVE_TO_ARGS) { array ->
@@ -133,7 +133,7 @@
}
RelativeLineToKey -> pathNodesFromArgs(args, NUM_LINE_TO_ARGS) { array ->
- PathNode.RelativeLineTo(x = array[0], y = array[1])
+ PathNode.RelativeLineTo(dx = array[0], dy = array[1])
}
LineToKey -> pathNodesFromArgs(args, NUM_LINE_TO_ARGS) { array ->
@@ -141,7 +141,7 @@
}
RelativeHorizontalToKey -> pathNodesFromArgs(args, NUM_HORIZONTAL_TO_ARGS) { array ->
- PathNode.RelativeHorizontalTo(x = array[0])
+ PathNode.RelativeHorizontalTo(dx = array[0])
}
HorizontalToKey -> pathNodesFromArgs(args, NUM_HORIZONTAL_TO_ARGS) { array ->
@@ -149,7 +149,7 @@
}
RelativeVerticalToKey -> pathNodesFromArgs(args, NUM_VERTICAL_TO_ARGS) { array ->
- PathNode.RelativeVerticalTo(y = array[0])
+ PathNode.RelativeVerticalTo(dy = array[0])
}
VerticalToKey -> pathNodesFromArgs(args, NUM_VERTICAL_TO_ARGS) { array ->
@@ -180,10 +180,10 @@
RelativeReflectiveCurveToKey -> pathNodesFromArgs(args, NUM_REFLECTIVE_CURVE_TO_ARGS) { array ->
PathNode.RelativeReflectiveCurveTo(
- x1 = array[0],
- y1 = array[1],
- x2 = array[2],
- y2 = array[3]
+ dx1 = array[0],
+ dy1 = array[1],
+ dx2 = array[2],
+ dy2 = array[3]
)
}
@@ -198,10 +198,10 @@
RelativeQuadToKey -> pathNodesFromArgs(args, NUM_QUAD_TO_ARGS) { array ->
PathNode.RelativeQuadTo(
- x1 = array[0],
- y1 = array[1],
- x2 = array[2],
- y2 = array[3]
+ dx1 = array[0],
+ dy1 = array[1],
+ dx2 = array[2],
+ dy2 = array[3]
)
}
@@ -215,7 +215,7 @@
}
RelativeReflectiveQuadToKey -> pathNodesFromArgs(args, NUM_REFLECTIVE_QUAD_TO_ARGS) { array ->
- PathNode.RelativeReflectiveQuadTo(x = array[0], y = array[1])
+ PathNode.RelativeReflectiveQuadTo(dx = array[0], dy = array[1])
}
ReflectiveQuadToKey -> pathNodesFromArgs(args, NUM_REFLECTIVE_QUAD_TO_ARGS) { array ->
diff --git a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt
index 84e299b..4de210b 100644
--- a/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt
+++ b/ui/ui-graphics/src/commonMain/kotlin/androidx/ui/graphics/vector/PathParser.kt
@@ -152,9 +152,9 @@
}
private fun RelativeMoveTo.relativeMoveTo(target: Path) {
- currentPoint.x += x
- currentPoint.y += y
- target.relativeMoveTo(x, y)
+ currentPoint.x += dx
+ currentPoint.y += dy
+ target.relativeMoveTo(dx, dy)
segmentPoint.x = currentPoint.x
segmentPoint.y = currentPoint.y
}
@@ -168,9 +168,9 @@
}
private fun RelativeLineTo.relativeLineTo(target: Path) {
- target.relativeLineTo(x, y)
- currentPoint.x += x
- currentPoint.y += y
+ target.relativeLineTo(dx, dy)
+ currentPoint.x += dx
+ currentPoint.y += dy
}
private fun LineTo.lineTo(target: Path) {
@@ -180,8 +180,8 @@
}
private fun RelativeHorizontalTo.relativeHorizontalTo(target: Path) {
- target.relativeLineTo(x, 0.0f)
- currentPoint.x += x
+ target.relativeLineTo(dx, 0.0f)
+ currentPoint.x += dx
}
private fun HorizontalTo.horizontalTo(target: Path) {
@@ -190,8 +190,8 @@
}
private fun RelativeVerticalTo.relativeVerticalTo(target: Path) {
- target.relativeLineTo(0.0f, y)
- currentPoint.y += y
+ target.relativeLineTo(0.0f, dy)
+ currentPoint.y += dy
}
private fun VerticalTo.verticalTo(target: Path) {
@@ -236,13 +236,13 @@
target.relativeCubicTo(
reflectiveCtrlPoint.x, reflectiveCtrlPoint.y,
- x1, y1,
- x2, y2
+ dx1, dy1,
+ dx2, dy2
)
- ctrlPoint.x = currentPoint.x + x1
- ctrlPoint.y = currentPoint.y + y1
- currentPoint.x += x2
- currentPoint.y += y2
+ ctrlPoint.x = currentPoint.x + dx1
+ ctrlPoint.y = currentPoint.y + dy1
+ currentPoint.x += dx2
+ currentPoint.y += dy2
}
private fun ReflectiveCurveTo.reflectiveCurveTo(prevIsCurve: Boolean, target: Path) {
@@ -265,11 +265,11 @@
}
private fun RelativeQuadTo.relativeQuadTo(target: Path) {
- target.relativeQuadraticBezierTo(x1, y1, x2, y2)
- ctrlPoint.x = currentPoint.x + x1
- ctrlPoint.y = currentPoint.y + y1
- currentPoint.x += x1
- currentPoint.y += y1
+ target.relativeQuadraticBezierTo(dx1, dy1, dx2, dy2)
+ ctrlPoint.x = currentPoint.x + dx1
+ ctrlPoint.y = currentPoint.y + dy1
+ currentPoint.x += dx1
+ currentPoint.y += dy1
}
private fun QuadTo.quadTo(target: Path) {
@@ -293,12 +293,12 @@
target.relativeQuadraticBezierTo(
reflectiveCtrlPoint.x,
- reflectiveCtrlPoint.y, x, y
+ reflectiveCtrlPoint.y, dx, dy
)
ctrlPoint.x = currentPoint.x + reflectiveCtrlPoint.x
ctrlPoint.y = currentPoint.y + reflectiveCtrlPoint.y
- currentPoint.x += x
- currentPoint.y += y
+ currentPoint.x += dx
+ currentPoint.y += dy
}
private fun ReflectiveQuadTo.reflectiveQuadTo(prevIsQuad: Boolean, target: Path) {
diff --git a/ui/ui-layout/api/0.1.0-dev15.txt b/ui/ui-layout/api/0.1.0-dev15.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/0.1.0-dev15.txt
+++ b/ui/ui-layout/api/0.1.0-dev15.txt
@@ -8,22 +8,22 @@
@androidx.compose.Immutable public interface Arrangement {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
}
public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
}
public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
}
public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.End INSTANCE;
}
public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
}
public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
}
public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
}
public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
}
public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
}
public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
}
public final class ChainStyle {
- field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+ field public static final androidx.ui.layout.ChainStyle.Companion Companion;
}
public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+ field public static final androidx.ui.layout.ColumnScope INSTANCE;
}
@androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
- field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
}
@androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
- field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+ field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
}
public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
}
public interface Dimension {
- field public static final androidx.ui.layout.Dimension.Companion! Companion;
+ field public static final androidx.ui.layout.Dimension.Companion Companion;
}
public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
method public float getMaxWidth();
method public float getMinHeight();
method public float getMinWidth();
- field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+ field public static final androidx.ui.layout.DpConstraints.Companion Companion;
}
public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
}
public enum FlowCrossAxisAlignment {
+ method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
}
public enum IntrinsicSize {
+ method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.IntrinsicSize[] values();
enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
}
@@ -581,6 +585,8 @@
}
public enum MainAxisAlignment {
+ method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.MainAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.RowScope! INSTANCE;
+ field public static final androidx.ui.layout.RowScope INSTANCE;
}
public enum SizeMode {
+ method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.SizeMode[] values();
enum_constant public static final androidx.ui.layout.SizeMode Expand;
enum_constant public static final androidx.ui.layout.SizeMode Wrap;
}
diff --git a/ui/ui-layout/api/current.txt b/ui/ui-layout/api/current.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/current.txt
+++ b/ui/ui-layout/api/current.txt
@@ -8,22 +8,22 @@
@androidx.compose.Immutable public interface Arrangement {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
}
public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
}
public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
}
public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.End INSTANCE;
}
public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
}
public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
}
public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
}
public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
}
public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
}
public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
}
public final class ChainStyle {
- field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+ field public static final androidx.ui.layout.ChainStyle.Companion Companion;
}
public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+ field public static final androidx.ui.layout.ColumnScope INSTANCE;
}
@androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
- field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
}
@androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
- field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+ field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
}
public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
}
public interface Dimension {
- field public static final androidx.ui.layout.Dimension.Companion! Companion;
+ field public static final androidx.ui.layout.Dimension.Companion Companion;
}
public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
method public float getMaxWidth();
method public float getMinHeight();
method public float getMinWidth();
- field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+ field public static final androidx.ui.layout.DpConstraints.Companion Companion;
}
public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
}
public enum FlowCrossAxisAlignment {
+ method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
}
public enum IntrinsicSize {
+ method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.IntrinsicSize[] values();
enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
}
@@ -581,6 +585,8 @@
}
public enum MainAxisAlignment {
+ method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.MainAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.RowScope! INSTANCE;
+ field public static final androidx.ui.layout.RowScope INSTANCE;
}
public enum SizeMode {
+ method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.SizeMode[] values();
enum_constant public static final androidx.ui.layout.SizeMode Expand;
enum_constant public static final androidx.ui.layout.SizeMode Wrap;
}
diff --git a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-layout/api/public_plus_experimental_0.1.0-dev15.txt
@@ -8,22 +8,22 @@
@androidx.compose.Immutable public interface Arrangement {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
}
public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
}
public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
}
public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.End INSTANCE;
}
public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
}
public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
}
public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
}
public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
}
public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
}
public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
}
public final class ChainStyle {
- field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+ field public static final androidx.ui.layout.ChainStyle.Companion Companion;
}
public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+ field public static final androidx.ui.layout.ColumnScope INSTANCE;
}
@androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
- field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
}
@androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
- field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+ field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
}
public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
}
public interface Dimension {
- field public static final androidx.ui.layout.Dimension.Companion! Companion;
+ field public static final androidx.ui.layout.Dimension.Companion Companion;
}
public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
method public float getMaxWidth();
method public float getMinHeight();
method public float getMinWidth();
- field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+ field public static final androidx.ui.layout.DpConstraints.Companion Companion;
}
public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
}
public enum FlowCrossAxisAlignment {
+ method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
}
public enum IntrinsicSize {
+ method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.IntrinsicSize[] values();
enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
}
@@ -581,6 +585,8 @@
}
public enum MainAxisAlignment {
+ method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.MainAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.RowScope! INSTANCE;
+ field public static final androidx.ui.layout.RowScope INSTANCE;
}
public enum SizeMode {
+ method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.SizeMode[] values();
enum_constant public static final androidx.ui.layout.SizeMode Expand;
enum_constant public static final androidx.ui.layout.SizeMode Wrap;
}
diff --git a/ui/ui-layout/api/public_plus_experimental_current.txt b/ui/ui-layout/api/public_plus_experimental_current.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/public_plus_experimental_current.txt
+++ b/ui/ui-layout/api/public_plus_experimental_current.txt
@@ -8,22 +8,22 @@
@androidx.compose.Immutable public interface Arrangement {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
}
public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
}
public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
}
public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.End INSTANCE;
}
public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
}
public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
}
public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
}
public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
}
public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
}
public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
}
public final class ChainStyle {
- field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+ field public static final androidx.ui.layout.ChainStyle.Companion Companion;
}
public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+ field public static final androidx.ui.layout.ColumnScope INSTANCE;
}
@androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
- field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
}
@androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
- field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+ field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
}
public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
}
public interface Dimension {
- field public static final androidx.ui.layout.Dimension.Companion! Companion;
+ field public static final androidx.ui.layout.Dimension.Companion Companion;
}
public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
method public float getMaxWidth();
method public float getMinHeight();
method public float getMinWidth();
- field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+ field public static final androidx.ui.layout.DpConstraints.Companion Companion;
}
public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
}
public enum FlowCrossAxisAlignment {
+ method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
}
public enum IntrinsicSize {
+ method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.IntrinsicSize[] values();
enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
}
@@ -581,6 +585,8 @@
}
public enum MainAxisAlignment {
+ method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.MainAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.RowScope! INSTANCE;
+ field public static final androidx.ui.layout.RowScope INSTANCE;
}
public enum SizeMode {
+ method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.SizeMode[] values();
enum_constant public static final androidx.ui.layout.SizeMode Expand;
enum_constant public static final androidx.ui.layout.SizeMode Wrap;
}
diff --git a/ui/ui-layout/api/restricted_0.1.0-dev15.txt b/ui/ui-layout/api/restricted_0.1.0-dev15.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-layout/api/restricted_0.1.0-dev15.txt
@@ -8,22 +8,22 @@
@androidx.compose.Immutable public interface Arrangement {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
}
public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
}
public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
}
public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.End INSTANCE;
}
public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
}
public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
}
public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
}
public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
}
public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
}
public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
}
public final class ChainStyle {
- field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+ field public static final androidx.ui.layout.ChainStyle.Companion Companion;
}
public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+ field public static final androidx.ui.layout.ColumnScope INSTANCE;
}
@androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
- field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
}
@androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
- field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+ field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
}
public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
}
public interface Dimension {
- field public static final androidx.ui.layout.Dimension.Companion! Companion;
+ field public static final androidx.ui.layout.Dimension.Companion Companion;
}
public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
method public float getMaxWidth();
method public float getMinHeight();
method public float getMinWidth();
- field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+ field public static final androidx.ui.layout.DpConstraints.Companion Companion;
}
public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
}
public enum FlowCrossAxisAlignment {
+ method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
}
public enum IntrinsicSize {
+ method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.IntrinsicSize[] values();
enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
}
@@ -581,6 +585,8 @@
}
public enum MainAxisAlignment {
+ method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.MainAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.RowScope! INSTANCE;
+ field public static final androidx.ui.layout.RowScope INSTANCE;
}
public enum SizeMode {
+ method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.SizeMode[] values();
enum_constant public static final androidx.ui.layout.SizeMode Expand;
enum_constant public static final androidx.ui.layout.SizeMode Wrap;
}
diff --git a/ui/ui-layout/api/restricted_current.txt b/ui/ui-layout/api/restricted_current.txt
index d6dd40f..3b9fca9 100644
--- a/ui/ui-layout/api/restricted_current.txt
+++ b/ui/ui-layout/api/restricted_current.txt
@@ -8,22 +8,22 @@
@androidx.compose.Immutable public interface Arrangement {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field @Deprecated public static final androidx.ui.layout.Arrangement.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.Arrangement.Companion Companion;
}
public static final class Arrangement.Bottom implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Bottom! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Bottom INSTANCE;
}
public static final class Arrangement.Center implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Center! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Center INSTANCE;
}
public static final class Arrangement.End implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.End! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.End INSTANCE;
}
public static interface Arrangement.Horizontal extends androidx.ui.layout.Arrangement {
@@ -31,34 +31,34 @@
public static final class Arrangement.SpaceAround implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceAround! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceAround INSTANCE;
}
public static final class Arrangement.SpaceBetween implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceBetween! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceBetween INSTANCE;
}
public static final class Arrangement.SpaceEvenly implements androidx.ui.layout.Arrangement.Horizontal androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.SpaceEvenly! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.SpaceEvenly INSTANCE;
}
public static final class Arrangement.Start implements androidx.ui.layout.Arrangement.Horizontal {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Start! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Start INSTANCE;
}
public static final class Arrangement.Top implements androidx.ui.layout.Arrangement.Vertical {
method public java.util.List<java.lang.Integer> arrange(int totalSize, java.util.List<java.lang.Integer> size, androidx.ui.core.LayoutDirection layoutDirection);
- field public static final androidx.ui.layout.Arrangement.Top! INSTANCE;
+ field public static final androidx.ui.layout.Arrangement.Top INSTANCE;
}
public static interface Arrangement.Vertical extends androidx.ui.layout.Arrangement {
}
public final class ChainStyle {
- field public static final androidx.ui.layout.ChainStyle.Companion! Companion;
+ field public static final androidx.ui.layout.ChainStyle.Companion Companion;
}
public static final class ChainStyle.Companion {
@@ -80,7 +80,7 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Horizontal align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.ColumnScope! INSTANCE;
+ field public static final androidx.ui.layout.ColumnScope INSTANCE;
}
@androidx.ui.layout.LayoutScopeMarker public final class ConstrainScope {
@@ -273,7 +273,7 @@
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle {
- field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion! Companion;
+ field @Deprecated public static final androidx.ui.layout.ConstraintSetBuilderScope.ChainStyle.Companion Companion;
}
@Deprecated public static final class ConstraintSetBuilderScope.ChainStyle.Companion {
@@ -419,7 +419,7 @@
}
@androidx.compose.Immutable public abstract sealed class CrossAxisAlignment {
- field public static final androidx.ui.layout.CrossAxisAlignment.Companion! Companion;
+ field public static final androidx.ui.layout.CrossAxisAlignment.Companion Companion;
}
public static final class CrossAxisAlignment.Companion {
@@ -433,7 +433,7 @@
}
public interface Dimension {
- field public static final androidx.ui.layout.Dimension.Companion! Companion;
+ field public static final androidx.ui.layout.Dimension.Companion Companion;
}
public static interface Dimension.Coercible extends androidx.ui.layout.Dimension {
@@ -467,7 +467,7 @@
method public float getMaxWidth();
method public float getMinHeight();
method public float getMinWidth();
- field public static final androidx.ui.layout.DpConstraints.Companion! Companion;
+ field public static final androidx.ui.layout.DpConstraints.Companion Companion;
}
public static final class DpConstraints.Companion {
@@ -493,6 +493,8 @@
}
public enum FlowCrossAxisAlignment {
+ method public static androidx.ui.layout.FlowCrossAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.FlowCrossAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Center;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment End;
enum_constant public static final androidx.ui.layout.FlowCrossAxisAlignment Start;
@@ -525,6 +527,8 @@
}
public enum IntrinsicSize {
+ method public static androidx.ui.layout.IntrinsicSize valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.IntrinsicSize[] values();
enum_constant public static final androidx.ui.layout.IntrinsicSize Max;
enum_constant public static final androidx.ui.layout.IntrinsicSize Min;
}
@@ -581,6 +585,8 @@
}
public enum MainAxisAlignment {
+ method public static androidx.ui.layout.MainAxisAlignment valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.MainAxisAlignment[] values();
enum_constant public static final androidx.ui.layout.MainAxisAlignment Center;
enum_constant public static final androidx.ui.layout.MainAxisAlignment End;
enum_constant public static final androidx.ui.layout.MainAxisAlignment SpaceAround;
@@ -601,10 +607,12 @@
method @androidx.compose.Stable public androidx.ui.core.Modifier alignWithSiblings(androidx.ui.core.Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.core.Measured,java.lang.Integer> alignmentLineBlock);
method @androidx.compose.Stable public androidx.ui.core.Modifier gravity(androidx.ui.core.Modifier, androidx.ui.core.Alignment.Vertical align);
method @androidx.compose.Stable public androidx.ui.core.Modifier weight(androidx.ui.core.Modifier, @FloatRange(from=0.0, fromInclusive=false) float weight, boolean fill = true);
- field public static final androidx.ui.layout.RowScope! INSTANCE;
+ field public static final androidx.ui.layout.RowScope INSTANCE;
}
public enum SizeMode {
+ method public static androidx.ui.layout.SizeMode valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.layout.SizeMode[] values();
enum_constant public static final androidx.ui.layout.SizeMode Expand;
enum_constant public static final androidx.ui.layout.SizeMode Wrap;
}
diff --git a/ui/ui-material/api/0.1.0-dev15.txt b/ui/ui-material/api/0.1.0-dev15.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/0.1.0-dev15.txt
+++ b/ui/ui-material/api/0.1.0-dev15.txt
@@ -2,6 +2,8 @@
package androidx.ui.material {
public enum AlertDialogButtonLayout {
+ method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.AlertDialogButtonLayout[] values();
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
}
@@ -33,7 +35,7 @@
property public final float DefaultMinWidth;
property public final long defaultDisabledBackgroundColor;
property public final long defaultDisabledContentColor;
- field public static final androidx.ui.material.Button! INSTANCE;
+ field public static final androidx.ui.material.Button INSTANCE;
}
public final class ButtonKt {
@@ -94,7 +96,7 @@
public final class DrawerConstants {
method public float getDefaultElevation();
property public final float DefaultElevation;
- field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+ field public static final androidx.ui.material.DrawerConstants INSTANCE;
}
public final class DrawerKt {
@@ -103,6 +105,8 @@
}
public enum DrawerState {
+ method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.DrawerState[] values();
enum_constant public static final androidx.ui.material.DrawerState Closed;
enum_constant public static final androidx.ui.material.DrawerState Opened;
}
@@ -147,7 +151,7 @@
property public final androidx.ui.material.ColorPalette colors;
property public final androidx.ui.material.Shapes shapes;
property public final androidx.ui.material.Typography typography;
- field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+ field public static final androidx.ui.material.MaterialTheme INSTANCE;
}
public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
public final class ProgressIndicatorConstants {
method public float getDefaultStrokeWidth();
property public final float DefaultStrokeWidth;
- field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+ field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
}
public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
method public long getDefaultUnselectedColor();
property public final long defaultDisabledColor;
property public final long defaultUnselectedColor;
- field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+ field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
@@ -192,10 +196,12 @@
}
public final class Scaffold {
- field public static final androidx.ui.material.Scaffold! INSTANCE;
+ field public static final androidx.ui.material.Scaffold INSTANCE;
}
public enum Scaffold.FabPosition {
+ method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.Scaffold.FabPosition[] values();
enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
}
@@ -267,7 +273,7 @@
public final class TabRow {
method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
- field public static final androidx.ui.material.TabRow! INSTANCE;
+ field public static final androidx.ui.material.TabRow INSTANCE;
}
@androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
public final class TextButton {
method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
- field public static final androidx.ui.material.TextButton! INSTANCE;
+ field public static final androidx.ui.material.TextButton INSTANCE;
}
public final class TextFieldKt {
diff --git a/ui/ui-material/api/api_lint.ignore b/ui/ui-material/api/api_lint.ignore
deleted file mode 100644
index 7e1573a..0000000
--- a/ui/ui-material/api/api_lint.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-NotCloseable: androidx.ui.material.ripple.RippleEffect:
- Classes that release resources (finish()) should implement AutoClosable and CloseGuard: class androidx.ui.material.ripple.RippleEffect
diff --git a/ui/ui-material/api/current.txt b/ui/ui-material/api/current.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/current.txt
+++ b/ui/ui-material/api/current.txt
@@ -2,6 +2,8 @@
package androidx.ui.material {
public enum AlertDialogButtonLayout {
+ method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.AlertDialogButtonLayout[] values();
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
}
@@ -33,7 +35,7 @@
property public final float DefaultMinWidth;
property public final long defaultDisabledBackgroundColor;
property public final long defaultDisabledContentColor;
- field public static final androidx.ui.material.Button! INSTANCE;
+ field public static final androidx.ui.material.Button INSTANCE;
}
public final class ButtonKt {
@@ -94,7 +96,7 @@
public final class DrawerConstants {
method public float getDefaultElevation();
property public final float DefaultElevation;
- field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+ field public static final androidx.ui.material.DrawerConstants INSTANCE;
}
public final class DrawerKt {
@@ -103,6 +105,8 @@
}
public enum DrawerState {
+ method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.DrawerState[] values();
enum_constant public static final androidx.ui.material.DrawerState Closed;
enum_constant public static final androidx.ui.material.DrawerState Opened;
}
@@ -147,7 +151,7 @@
property public final androidx.ui.material.ColorPalette colors;
property public final androidx.ui.material.Shapes shapes;
property public final androidx.ui.material.Typography typography;
- field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+ field public static final androidx.ui.material.MaterialTheme INSTANCE;
}
public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
public final class ProgressIndicatorConstants {
method public float getDefaultStrokeWidth();
property public final float DefaultStrokeWidth;
- field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+ field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
}
public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
method public long getDefaultUnselectedColor();
property public final long defaultDisabledColor;
property public final long defaultUnselectedColor;
- field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+ field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
@@ -192,10 +196,12 @@
}
public final class Scaffold {
- field public static final androidx.ui.material.Scaffold! INSTANCE;
+ field public static final androidx.ui.material.Scaffold INSTANCE;
}
public enum Scaffold.FabPosition {
+ method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.Scaffold.FabPosition[] values();
enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
}
@@ -267,7 +273,7 @@
public final class TabRow {
method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
- field public static final androidx.ui.material.TabRow! INSTANCE;
+ field public static final androidx.ui.material.TabRow INSTANCE;
}
@androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
public final class TextButton {
method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
- field public static final androidx.ui.material.TextButton! INSTANCE;
+ field public static final androidx.ui.material.TextButton INSTANCE;
}
public final class TextFieldKt {
diff --git a/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-material/api/public_plus_experimental_0.1.0-dev15.txt
@@ -2,6 +2,8 @@
package androidx.ui.material {
public enum AlertDialogButtonLayout {
+ method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.AlertDialogButtonLayout[] values();
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
}
@@ -33,7 +35,7 @@
property public final float DefaultMinWidth;
property public final long defaultDisabledBackgroundColor;
property public final long defaultDisabledContentColor;
- field public static final androidx.ui.material.Button! INSTANCE;
+ field public static final androidx.ui.material.Button INSTANCE;
}
public final class ButtonKt {
@@ -94,7 +96,7 @@
public final class DrawerConstants {
method public float getDefaultElevation();
property public final float DefaultElevation;
- field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+ field public static final androidx.ui.material.DrawerConstants INSTANCE;
}
public final class DrawerKt {
@@ -103,6 +105,8 @@
}
public enum DrawerState {
+ method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.DrawerState[] values();
enum_constant public static final androidx.ui.material.DrawerState Closed;
enum_constant public static final androidx.ui.material.DrawerState Opened;
}
@@ -147,7 +151,7 @@
property public final androidx.ui.material.ColorPalette colors;
property public final androidx.ui.material.Shapes shapes;
property public final androidx.ui.material.Typography typography;
- field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+ field public static final androidx.ui.material.MaterialTheme INSTANCE;
}
public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
public final class ProgressIndicatorConstants {
method public float getDefaultStrokeWidth();
property public final float DefaultStrokeWidth;
- field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+ field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
}
public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
method public long getDefaultUnselectedColor();
property public final long defaultDisabledColor;
property public final long defaultUnselectedColor;
- field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+ field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
@@ -192,10 +196,12 @@
}
public final class Scaffold {
- field public static final androidx.ui.material.Scaffold! INSTANCE;
+ field public static final androidx.ui.material.Scaffold INSTANCE;
}
public enum Scaffold.FabPosition {
+ method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.Scaffold.FabPosition[] values();
enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
}
@@ -267,7 +273,7 @@
public final class TabRow {
method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
- field public static final androidx.ui.material.TabRow! INSTANCE;
+ field public static final androidx.ui.material.TabRow INSTANCE;
}
@androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
public final class TextButton {
method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
- field public static final androidx.ui.material.TextButton! INSTANCE;
+ field public static final androidx.ui.material.TextButton INSTANCE;
}
public final class TextFieldKt {
diff --git a/ui/ui-material/api/public_plus_experimental_current.txt b/ui/ui-material/api/public_plus_experimental_current.txt
index e436065..dd6ea59 100644
--- a/ui/ui-material/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/api/public_plus_experimental_current.txt
@@ -2,6 +2,8 @@
package androidx.ui.material {
public enum AlertDialogButtonLayout {
+ method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.AlertDialogButtonLayout[] values();
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
}
@@ -33,7 +35,7 @@
property public final float DefaultMinWidth;
property public final long defaultDisabledBackgroundColor;
property public final long defaultDisabledContentColor;
- field public static final androidx.ui.material.Button! INSTANCE;
+ field public static final androidx.ui.material.Button INSTANCE;
}
public final class ButtonKt {
@@ -94,7 +96,7 @@
public final class DrawerConstants {
method public float getDefaultElevation();
property public final float DefaultElevation;
- field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+ field public static final androidx.ui.material.DrawerConstants INSTANCE;
}
public final class DrawerKt {
@@ -103,6 +105,8 @@
}
public enum DrawerState {
+ method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.DrawerState[] values();
enum_constant public static final androidx.ui.material.DrawerState Closed;
enum_constant public static final androidx.ui.material.DrawerState Opened;
}
@@ -147,7 +151,7 @@
property public final androidx.ui.material.ColorPalette colors;
property public final androidx.ui.material.Shapes shapes;
property public final androidx.ui.material.Typography typography;
- field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+ field public static final androidx.ui.material.MaterialTheme INSTANCE;
}
public final class MaterialThemeKt {
@@ -162,7 +166,7 @@
public final class ProgressIndicatorConstants {
method public float getDefaultStrokeWidth();
property public final float DefaultStrokeWidth;
- field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+ field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
}
public final class ProgressIndicatorKt {
@@ -177,7 +181,7 @@
method public long getDefaultUnselectedColor();
property public final long defaultDisabledColor;
property public final long defaultUnselectedColor;
- field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+ field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
@@ -192,10 +196,12 @@
}
public final class Scaffold {
- field public static final androidx.ui.material.Scaffold! INSTANCE;
+ field public static final androidx.ui.material.Scaffold INSTANCE;
}
public enum Scaffold.FabPosition {
+ method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.Scaffold.FabPosition[] values();
enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
}
@@ -267,7 +273,7 @@
public final class TabRow {
method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
- field public static final androidx.ui.material.TabRow! INSTANCE;
+ field public static final androidx.ui.material.TabRow INSTANCE;
}
@androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -283,7 +289,7 @@
public final class TextButton {
method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
- field public static final androidx.ui.material.TextButton! INSTANCE;
+ field public static final androidx.ui.material.TextButton INSTANCE;
}
public final class TextFieldKt {
diff --git a/ui/ui-material/api/restricted_0.1.0-dev15.txt b/ui/ui-material/api/restricted_0.1.0-dev15.txt
index 392ee62..798e755 100644
--- a/ui/ui-material/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-material/api/restricted_0.1.0-dev15.txt
@@ -2,6 +2,8 @@
package androidx.ui.material {
public enum AlertDialogButtonLayout {
+ method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.AlertDialogButtonLayout[] values();
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
}
@@ -33,7 +35,7 @@
property public final float DefaultMinWidth;
property public final long defaultDisabledBackgroundColor;
property public final long defaultDisabledContentColor;
- field public static final androidx.ui.material.Button! INSTANCE;
+ field public static final androidx.ui.material.Button INSTANCE;
}
public final class ButtonKt {
@@ -95,7 +97,7 @@
public final class DrawerConstants {
method public float getDefaultElevation();
property public final float DefaultElevation;
- field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+ field public static final androidx.ui.material.DrawerConstants INSTANCE;
}
public final class DrawerKt {
@@ -104,6 +106,8 @@
}
public enum DrawerState {
+ method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.DrawerState[] values();
enum_constant public static final androidx.ui.material.DrawerState Closed;
enum_constant public static final androidx.ui.material.DrawerState Opened;
}
@@ -148,7 +152,7 @@
property public final androidx.ui.material.ColorPalette colors;
property public final androidx.ui.material.Shapes shapes;
property public final androidx.ui.material.Typography typography;
- field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+ field public static final androidx.ui.material.MaterialTheme INSTANCE;
}
public final class MaterialThemeKt {
@@ -163,7 +167,7 @@
public final class ProgressIndicatorConstants {
method public float getDefaultStrokeWidth();
property public final float DefaultStrokeWidth;
- field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+ field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
}
public final class ProgressIndicatorKt {
@@ -178,7 +182,7 @@
method public long getDefaultUnselectedColor();
property public final long defaultDisabledColor;
property public final long defaultUnselectedColor;
- field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+ field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
@@ -193,10 +197,12 @@
}
public final class Scaffold {
- field public static final androidx.ui.material.Scaffold! INSTANCE;
+ field public static final androidx.ui.material.Scaffold INSTANCE;
}
public enum Scaffold.FabPosition {
+ method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.Scaffold.FabPosition[] values();
enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
}
@@ -268,7 +274,7 @@
public final class TabRow {
method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
- field public static final androidx.ui.material.TabRow! INSTANCE;
+ field public static final androidx.ui.material.TabRow INSTANCE;
}
@androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -284,7 +290,7 @@
public final class TextButton {
method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
- field public static final androidx.ui.material.TextButton! INSTANCE;
+ field public static final androidx.ui.material.TextButton INSTANCE;
}
public final class TextFieldKt {
diff --git a/ui/ui-material/api/restricted_current.txt b/ui/ui-material/api/restricted_current.txt
index 392ee62..798e755 100644
--- a/ui/ui-material/api/restricted_current.txt
+++ b/ui/ui-material/api/restricted_current.txt
@@ -2,6 +2,8 @@
package androidx.ui.material {
public enum AlertDialogButtonLayout {
+ method public static androidx.ui.material.AlertDialogButtonLayout valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.AlertDialogButtonLayout[] values();
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout SideBySide;
enum_constant public static final androidx.ui.material.AlertDialogButtonLayout Stacked;
}
@@ -33,7 +35,7 @@
property public final float DefaultMinWidth;
property public final long defaultDisabledBackgroundColor;
property public final long defaultDisabledContentColor;
- field public static final androidx.ui.material.Button! INSTANCE;
+ field public static final androidx.ui.material.Button INSTANCE;
}
public final class ButtonKt {
@@ -95,7 +97,7 @@
public final class DrawerConstants {
method public float getDefaultElevation();
property public final float DefaultElevation;
- field public static final androidx.ui.material.DrawerConstants! INSTANCE;
+ field public static final androidx.ui.material.DrawerConstants INSTANCE;
}
public final class DrawerKt {
@@ -104,6 +106,8 @@
}
public enum DrawerState {
+ method public static androidx.ui.material.DrawerState valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.DrawerState[] values();
enum_constant public static final androidx.ui.material.DrawerState Closed;
enum_constant public static final androidx.ui.material.DrawerState Opened;
}
@@ -148,7 +152,7 @@
property public final androidx.ui.material.ColorPalette colors;
property public final androidx.ui.material.Shapes shapes;
property public final androidx.ui.material.Typography typography;
- field public static final androidx.ui.material.MaterialTheme! INSTANCE;
+ field public static final androidx.ui.material.MaterialTheme INSTANCE;
}
public final class MaterialThemeKt {
@@ -163,7 +167,7 @@
public final class ProgressIndicatorConstants {
method public float getDefaultStrokeWidth();
property public final float DefaultStrokeWidth;
- field public static final androidx.ui.material.ProgressIndicatorConstants! INSTANCE;
+ field public static final androidx.ui.material.ProgressIndicatorConstants INSTANCE;
}
public final class ProgressIndicatorKt {
@@ -178,7 +182,7 @@
method public long getDefaultUnselectedColor();
property public final long defaultDisabledColor;
property public final long defaultUnselectedColor;
- field public static final androidx.ui.material.RadioButtonConstants! INSTANCE;
+ field public static final androidx.ui.material.RadioButtonConstants INSTANCE;
}
public final class RadioButtonKt {
@@ -193,10 +197,12 @@
}
public final class Scaffold {
- field public static final androidx.ui.material.Scaffold! INSTANCE;
+ field public static final androidx.ui.material.Scaffold INSTANCE;
}
public enum Scaffold.FabPosition {
+ method public static androidx.ui.material.Scaffold.FabPosition valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.material.Scaffold.FabPosition[] values();
enum_constant public static final androidx.ui.material.Scaffold.FabPosition Center;
enum_constant public static final androidx.ui.material.Scaffold.FabPosition End;
}
@@ -268,7 +274,7 @@
public final class TabRow {
method @androidx.compose.Composable public void Indicator-e8O-MNM(androidx.ui.core.Modifier modifier = Modifier, long color = contentColor());
method @androidx.compose.Composable public void IndicatorContainer(java.util.List<androidx.ui.material.TabRow.TabPosition> tabPositions, int selectedIndex, kotlin.jvm.functions.Function0<kotlin.Unit> indicator);
- field public static final androidx.ui.material.TabRow! INSTANCE;
+ field public static final androidx.ui.material.TabRow INSTANCE;
}
@androidx.compose.Immutable public static final class TabRow.TabPosition {
@@ -284,7 +290,7 @@
public final class TextButton {
method public androidx.ui.layout.InnerPadding getDefaultInnerPadding();
property public final androidx.ui.layout.InnerPadding DefaultInnerPadding;
- field public static final androidx.ui.material.TextButton! INSTANCE;
+ field public static final androidx.ui.material.TextButton INSTANCE;
}
public final class TextFieldKt {
diff --git a/ui/ui-material/icons/core/api/0.1.0-dev15.txt b/ui/ui-material/icons/core/api/0.1.0-dev15.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/0.1.0-dev15.txt
+++ b/ui/ui-material/icons/core/api/0.1.0-dev15.txt
@@ -4,27 +4,27 @@
public final class Icons {
method public androidx.ui.material.icons.Icons.Filled getDefault();
property public final androidx.ui.material.icons.Icons.Filled Default;
- field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons INSTANCE;
}
public static final class Icons.Filled {
- field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
}
public static final class Icons.Outlined {
- field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
}
public static final class Icons.Rounded {
- field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
}
public static final class Icons.Sharp {
- field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
}
public static final class Icons.TwoTone {
- field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
}
public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/current.txt b/ui/ui-material/icons/core/api/current.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/current.txt
+++ b/ui/ui-material/icons/core/api/current.txt
@@ -4,27 +4,27 @@
public final class Icons {
method public androidx.ui.material.icons.Icons.Filled getDefault();
property public final androidx.ui.material.icons.Icons.Filled Default;
- field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons INSTANCE;
}
public static final class Icons.Filled {
- field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
}
public static final class Icons.Outlined {
- field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
}
public static final class Icons.Rounded {
- field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
}
public static final class Icons.Sharp {
- field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
}
public static final class Icons.TwoTone {
- field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
}
public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -4,27 +4,27 @@
public final class Icons {
method public androidx.ui.material.icons.Icons.Filled getDefault();
property public final androidx.ui.material.icons.Icons.Filled Default;
- field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons INSTANCE;
}
public static final class Icons.Filled {
- field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
}
public static final class Icons.Outlined {
- field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
}
public static final class Icons.Rounded {
- field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
}
public static final class Icons.Sharp {
- field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
}
public static final class Icons.TwoTone {
- field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
}
public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/public_plus_experimental_current.txt b/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
@@ -4,27 +4,27 @@
public final class Icons {
method public androidx.ui.material.icons.Icons.Filled getDefault();
property public final androidx.ui.material.icons.Icons.Filled Default;
- field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons INSTANCE;
}
public static final class Icons.Filled {
- field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
}
public static final class Icons.Outlined {
- field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
}
public static final class Icons.Rounded {
- field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
}
public static final class Icons.Sharp {
- field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
}
public static final class Icons.TwoTone {
- field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
}
public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt b/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-material/icons/core/api/restricted_0.1.0-dev15.txt
@@ -4,27 +4,27 @@
public final class Icons {
method public androidx.ui.material.icons.Icons.Filled getDefault();
property public final androidx.ui.material.icons.Icons.Filled Default;
- field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons INSTANCE;
}
public static final class Icons.Filled {
- field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
}
public static final class Icons.Outlined {
- field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
}
public static final class Icons.Rounded {
- field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
}
public static final class Icons.Sharp {
- field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
}
public static final class Icons.TwoTone {
- field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
}
public final class IconsKt {
diff --git a/ui/ui-material/icons/core/api/restricted_current.txt b/ui/ui-material/icons/core/api/restricted_current.txt
index 49fcc65..e2d6896 100644
--- a/ui/ui-material/icons/core/api/restricted_current.txt
+++ b/ui/ui-material/icons/core/api/restricted_current.txt
@@ -4,27 +4,27 @@
public final class Icons {
method public androidx.ui.material.icons.Icons.Filled getDefault();
property public final androidx.ui.material.icons.Icons.Filled Default;
- field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons INSTANCE;
}
public static final class Icons.Filled {
- field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Filled INSTANCE;
}
public static final class Icons.Outlined {
- field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Outlined INSTANCE;
}
public static final class Icons.Rounded {
- field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Rounded INSTANCE;
}
public static final class Icons.Sharp {
- field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.Sharp INSTANCE;
}
public static final class Icons.TwoTone {
- field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ field public static final androidx.ui.material.icons.Icons.TwoTone INSTANCE;
}
public final class IconsKt {
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt
index 1fbd36c..ced42dc 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ButtonDemo.kt
@@ -20,6 +20,7 @@
import androidx.ui.core.Modifier
import androidx.ui.foundation.Border
import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
import androidx.ui.foundation.shape.GenericShape
import androidx.ui.graphics.Color
import androidx.ui.layout.Arrangement
@@ -48,14 +49,16 @@
@Composable
fun ButtonDemo() {
- Column(Modifier.padding(10.dp)) {
- Buttons()
- Spacer(Modifier.preferredHeight(DefaultSpace))
- Fabs()
- Spacer(Modifier.preferredHeight(DefaultSpace))
- IconButtons()
- Spacer(Modifier.preferredHeight(DefaultSpace))
- CustomShapeButton()
+ VerticalScroller {
+ Column(Modifier.padding(10.dp)) {
+ Buttons()
+ Spacer(Modifier.preferredHeight(DefaultSpace))
+ Fabs()
+ Spacer(Modifier.preferredHeight(DefaultSpace))
+ IconButtons()
+ Spacer(Modifier.preferredHeight(DefaultSpace))
+ CustomShapeButton()
+ }
}
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt
index 01b89bb..d0bfe90 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ListItemDemo.kt
@@ -18,6 +18,8 @@
import androidx.compose.Composable
import androidx.ui.foundation.VerticalScroller
+import androidx.ui.material.icons.Icons
+import androidx.ui.material.icons.filled.Call
import androidx.ui.material.samples.OneLineListItems
import androidx.ui.material.samples.ThreeLineListItems
import androidx.ui.material.samples.TwoLineListItems
@@ -28,9 +30,10 @@
val icon24 = imageResource(R.drawable.ic_bluetooth)
val icon40 = imageResource(R.drawable.ic_account_box)
val icon56 = imageResource(R.drawable.ic_android)
+ val vectorIcon = Icons.Default.Call
VerticalScroller {
- OneLineListItems(icon24, icon40, icon56)
+ OneLineListItems(icon24, icon40, icon56, vectorIcon)
TwoLineListItems(icon24, icon40)
- ThreeLineListItems(icon24, icon40)
+ ThreeLineListItems(icon24, vectorIcon)
}
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt
index f7c1dbb..98fe32d 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialDemos.kt
@@ -30,9 +30,9 @@
ComposableDemo("App Bars") { AppBarDemo() },
ComposableDemo("Bottom Navigation") { BottomNavigationDemo() },
ComposableDemo("Buttons & FABs") { ButtonDemo() },
- DemoCategory("Drawer", listOf(
- ComposableDemo("Modal") { ModalDrawerSample() },
- ComposableDemo("Bottom") { BottomDrawerSample() }
+ DemoCategory("Navigation drawer", listOf(
+ ComposableDemo("Modal drawer") { ModalDrawerSample() },
+ ComposableDemo("Bottom drawer") { BottomDrawerSample() }
)),
ComposableDemo("Elevation") { ElevationDemo() },
ComposableDemo("Emphasis") { EmphasisSample() },
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt
index cc4b52a..fea676e 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MaterialTextField.kt
@@ -84,116 +84,122 @@
@Composable
fun MaterialTextFieldDemo() {
- Column(Modifier.padding(10.dp)) {
- var text by savedInstanceState { "" }
- var leadingChecked by savedInstanceState { false }
- var trailingChecked by savedInstanceState { false }
- val characterCounterChecked by savedInstanceState { false }
- var selectedOption by savedInstanceState { Option.None }
- var selectedTextField by savedInstanceState { TextFieldType.Filled }
+ VerticalScroller {
+ Column(Modifier.padding(10.dp)) {
+ var text by savedInstanceState { "" }
+ var leadingChecked by savedInstanceState { false }
+ var trailingChecked by savedInstanceState { false }
+ val characterCounterChecked by savedInstanceState { false }
+ var selectedOption by savedInstanceState { Option.None }
+ var selectedTextField by savedInstanceState { TextFieldType.Filled }
- val textField: @Composable () -> Unit = @Composable {
- when (selectedTextField) {
- TextFieldType.Filled ->
- FilledTextField(
- value = text,
- onValueChange = { text = it },
- label = {
- val label = "Label" + if (selectedOption == Option.Error) "*" else ""
- Text(text = label)
- },
- leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
- trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
- isErrorValue = selectedOption == Option.Error
- )
- TextFieldType.Outlined ->
- OutlinedTextField(
- value = text,
- onValueChange = { text = it },
- label = {
- val label = "Label" + if (selectedOption == Option.Error) "*" else ""
- Text(text = label)
- },
- leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
- trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
- isErrorValue = selectedOption == Option.Error
- )
- }
- }
-
- Box(Modifier.preferredHeight(150.dp).gravity(Alignment.CenterHorizontally)) {
- if (selectedOption == Option.None) {
- textField()
- } else {
- TextFieldWithMessage(textField, selectedOption)
- }
- }
-
- Column {
- Title("Text field type")
- Column {
- TextFieldType.values().map { it.name }.forEach { textType ->
- Row(Modifier
- .fillMaxWidth()
- .selectable(
- selected = (textType == selectedTextField.name),
- onClick = { selectedTextField = TextFieldType.valueOf(textType) }
+ val textField: @Composable () -> Unit = @Composable {
+ when (selectedTextField) {
+ TextFieldType.Filled ->
+ FilledTextField(
+ value = text,
+ onValueChange = { text = it },
+ label = {
+ val label =
+ "Label" + if (selectedOption == Option.Error) "*" else ""
+ Text(text = label)
+ },
+ leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
+ trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
+ isErrorValue = selectedOption == Option.Error
)
- .padding(horizontal = 16.dp)
- ) {
- RadioButton(
- selected = (textType == selectedTextField.name),
- onClick = { selectedTextField = TextFieldType.valueOf(textType) }
+ TextFieldType.Outlined ->
+ OutlinedTextField(
+ value = text,
+ onValueChange = { text = it },
+ label = {
+ val label =
+ "Label" + if (selectedOption == Option.Error) "*" else ""
+ Text(text = label)
+ },
+ leadingIcon = { if (leadingChecked) Icon(Icons.Filled.Favorite) },
+ trailingIcon = { if (trailingChecked) Icon(Icons.Filled.Info) },
+ isErrorValue = selectedOption == Option.Error
)
- Text(
- text = textType,
- style = MaterialTheme.typography.body1.merge(),
- modifier = Modifier.padding(start = 16.dp)
- )
- }
}
}
- Title("Options")
- OptionRow(
- title = "Leading icon",
- checked = leadingChecked,
- onCheckedChange = { leadingChecked = it }
- )
- OptionRow(
- title = "Trailing icon",
- checked = trailingChecked,
- onCheckedChange = { trailingChecked = it }
- )
- OptionRow(
- title = "Character counter (TODO)",
- checked = characterCounterChecked,
- enabled = false,
- onCheckedChange = { /* TODO */ }
- )
+ Box(Modifier.preferredHeight(150.dp).gravity(Alignment.CenterHorizontally)) {
+ if (selectedOption == Option.None) {
+ textField()
+ } else {
+ TextFieldWithMessage(textField, selectedOption)
+ }
+ }
- Spacer(Modifier.preferredHeight(20.dp))
-
- Title("Assistive text")
Column {
- Option.values().map { it.name }.forEach { text ->
- Row(Modifier
- .fillMaxWidth()
- .selectable(
- selected = (text == selectedOption.name),
- onClick = { selectedOption = Option.valueOf(text) }
- )
- .padding(horizontal = 16.dp)
- ) {
- RadioButton(
- selected = (text == selectedOption.name),
- onClick = { selectedOption = Option.valueOf(text) }
- )
- Text(
- text = text,
- style = MaterialTheme.typography.body1.merge(),
- modifier = Modifier.padding(start = 16.dp)
- )
+ Title("Text field type")
+ Column {
+ TextFieldType.values().map { it.name }.forEach { textType ->
+ Row(Modifier
+ .fillMaxWidth()
+ .selectable(
+ selected = (textType == selectedTextField.name),
+ onClick = {
+ selectedTextField = TextFieldType.valueOf(textType)
+ }
+ )
+ .padding(horizontal = 16.dp)
+ ) {
+ RadioButton(
+ selected = (textType == selectedTextField.name),
+ onClick = { selectedTextField = TextFieldType.valueOf(textType) }
+ )
+ Text(
+ text = textType,
+ style = MaterialTheme.typography.body1.merge(),
+ modifier = Modifier.padding(start = 16.dp)
+ )
+ }
+ }
+ }
+
+ Title("Options")
+ OptionRow(
+ title = "Leading icon",
+ checked = leadingChecked,
+ onCheckedChange = { leadingChecked = it }
+ )
+ OptionRow(
+ title = "Trailing icon",
+ checked = trailingChecked,
+ onCheckedChange = { trailingChecked = it }
+ )
+ OptionRow(
+ title = "Character counter (TODO)",
+ checked = characterCounterChecked,
+ enabled = false,
+ onCheckedChange = { /* TODO */ }
+ )
+
+ Spacer(Modifier.preferredHeight(20.dp))
+
+ Title("Assistive text")
+ Column {
+ Option.values().map { it.name }.forEach { text ->
+ Row(Modifier
+ .fillMaxWidth()
+ .selectable(
+ selected = (text == selectedOption.name),
+ onClick = { selectedOption = Option.valueOf(text) }
+ )
+ .padding(horizontal = 16.dp)
+ ) {
+ RadioButton(
+ selected = (text == selectedOption.name),
+ onClick = { selectedOption = Option.valueOf(text) }
+ )
+ Text(
+ text = text,
+ style = MaterialTheme.typography.body1.merge(),
+ modifier = Modifier.padding(start = 16.dp)
+ )
+ }
}
}
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt
index 6b3adf7..4331d1b 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/ProgressIndicatorDemo.kt
@@ -28,9 +28,9 @@
import androidx.compose.setValue
import androidx.ui.core.Alignment
import androidx.ui.core.Modifier
+import androidx.ui.foundation.VerticalScroller
import androidx.ui.graphics.Color
import androidx.ui.layout.Arrangement
-import androidx.ui.layout.Column
import androidx.ui.layout.Row
import androidx.ui.layout.fillMaxWidth
import androidx.ui.material.CircularProgressIndicator
@@ -43,7 +43,7 @@
onActive { state.start() }
onDispose { state.stop() }
- Column {
+ VerticalScroller {
val modifier = Modifier.weight(1f, true)
.gravity(Alignment.CenterHorizontally)
.fillMaxWidth()
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt
index 820718f..485a171 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SelectionControlsDemo.kt
@@ -19,8 +19,11 @@
import androidx.compose.Composable
import androidx.ui.core.Modifier
import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
import androidx.ui.layout.Arrangement
import androidx.ui.layout.Column
+import androidx.ui.layout.Spacer
+import androidx.ui.layout.height
import androidx.ui.layout.padding
import androidx.ui.material.MaterialTheme
import androidx.ui.material.samples.RadioGroupSample
@@ -32,14 +35,19 @@
@Composable
fun SelectionControlsDemo() {
val headerStyle = MaterialTheme.typography.h6
- Column(Modifier.padding(10.dp), verticalArrangement = Arrangement.SpaceEvenly) {
- Text(text = "Checkbox", style = headerStyle)
- TriStateCheckboxSample()
- Text(text = "Switch", style = headerStyle)
- SwitchSample()
- Text(text = "RadioButton", style = headerStyle)
- RadioButtonSample()
- Text(text = "Radio group", style = headerStyle)
- RadioGroupSample()
+ VerticalScroller {
+ Column(Modifier.padding(10.dp), verticalArrangement = Arrangement.SpaceEvenly) {
+ Text(text = "Checkbox", style = headerStyle)
+ TriStateCheckboxSample()
+ Spacer(Modifier.height(16.dp))
+ Text(text = "Switch", style = headerStyle)
+ SwitchSample()
+ Spacer(Modifier.height(16.dp))
+ Text(text = "RadioButtons with custom colors", style = headerStyle)
+ RadioButtonSample()
+ Spacer(Modifier.height(16.dp))
+ Text(text = "Radio group", style = headerStyle)
+ RadioGroupSample()
+ }
}
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt
index 93c46cd..9913748 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SliderDemo.kt
@@ -18,16 +18,26 @@
import androidx.compose.Composable
import androidx.ui.core.Modifier
+import androidx.ui.foundation.Text
import androidx.ui.layout.Column
+import androidx.ui.layout.Spacer
+import androidx.ui.layout.height
import androidx.ui.layout.padding
+import androidx.ui.material.MaterialTheme
import androidx.ui.material.samples.SliderSample
import androidx.ui.material.samples.StepsSliderSample
import androidx.ui.unit.dp
@Composable
fun SliderDemo() {
+ val headerStyle = MaterialTheme.typography.h6
Column(Modifier.padding(10.dp)) {
+ Text(text = "Continuous Slider", style = headerStyle)
+ Spacer(Modifier.height(16.dp))
SliderSample()
+ Spacer(Modifier.height(16.dp))
+ Text(text = "Discrete Slider with custom color", style = headerStyle)
+ Spacer(Modifier.height(16.dp))
StepsSliderSample()
}
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt
index a605bce..26c8ba3 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/SnackbarDemo.kt
@@ -19,6 +19,7 @@
import androidx.compose.Composable
import androidx.ui.core.Modifier
import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
import androidx.ui.layout.Column
import androidx.ui.layout.padding
import androidx.ui.material.MaterialTheme
@@ -30,22 +31,24 @@
@Composable
fun SnackbarDemo() {
- Column(Modifier.padding(12.dp, 0.dp, 12.dp, 0.dp)) {
- val textSpacing = Modifier.padding(top = 12.dp, bottom = 12.dp)
- Text("Default Snackbar", modifier = textSpacing)
- SimpleSnackbar()
- Text("Snackbar with long text", modifier = textSpacing)
- Snackbar(
- text = { Text("This song already exists in the current playlist") },
- action = {
- TextButton(
- contentColor = snackbarPrimaryColorFor(MaterialTheme.colors),
- onClick = { /* perform undo */ }
- ) {
- Text("ADD THIS SONG ANYWAY")
- }
- },
- actionOnNewLine = true
- )
+ VerticalScroller {
+ Column(Modifier.padding(12.dp, 0.dp, 12.dp, 0.dp)) {
+ val textSpacing = Modifier.padding(top = 12.dp, bottom = 12.dp)
+ Text("Default Snackbar", modifier = textSpacing)
+ SimpleSnackbar()
+ Text("Snackbar with long text", modifier = textSpacing)
+ Snackbar(
+ text = { Text("This song already exists in the current playlist") },
+ action = {
+ TextButton(
+ contentColor = snackbarPrimaryColorFor(MaterialTheme.colors),
+ onClick = { /* perform undo */ }
+ ) {
+ Text("ADD THIS SONG ANYWAY")
+ }
+ },
+ actionOnNewLine = true
+ )
+ }
}
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt
index 8321760..545d0f6 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/TabDemo.kt
@@ -21,11 +21,10 @@
import androidx.ui.core.Alignment
import androidx.ui.core.Modifier
import androidx.ui.foundation.Text
+import androidx.ui.foundation.VerticalScroller
import androidx.ui.graphics.Color
-import androidx.ui.layout.Arrangement
-import androidx.ui.layout.Column
import androidx.ui.layout.Spacer
-import androidx.ui.layout.fillMaxHeight
+import androidx.ui.layout.height
import androidx.ui.layout.preferredHeight
import androidx.ui.material.Button
import androidx.ui.material.samples.FancyIndicatorContainerTabs
@@ -40,21 +39,29 @@
@Composable
fun TabDemo() {
- Column(Modifier.fillMaxHeight(), verticalArrangement = Arrangement.SpaceBetween) {
+ VerticalScroller {
val showingSimple = state { true }
val buttonText = "Show ${if (showingSimple.value) "custom" else "simple"} tabs"
+ Spacer(Modifier.height(24.dp))
if (showingSimple.value) {
TextTabs()
+ Spacer(Modifier.height(24.dp))
IconTabs()
+ Spacer(Modifier.height(24.dp))
TextAndIconTabs()
+ Spacer(Modifier.height(24.dp))
ScrollingTextTabs()
} else {
FancyTabs()
+ Spacer(Modifier.height(24.dp))
FancyIndicatorTabs()
+ Spacer(Modifier.height(24.dp))
FancyIndicatorContainerTabs()
+ Spacer(Modifier.height(24.dp))
ScrollingFancyIndicatorContainerTabs()
}
+ Spacer(Modifier.height(24.dp))
Button(
modifier = Modifier.gravity(Alignment.CenterHorizontally),
onClick = {
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt
index 2766566..22f5e6c 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/ListSamples.kt
@@ -18,16 +18,27 @@
import androidx.annotation.Sampled
import androidx.compose.Composable
+import androidx.compose.getValue
+import androidx.compose.setValue
+import androidx.compose.state
+import androidx.ui.foundation.Icon
import androidx.ui.foundation.Image
import androidx.ui.foundation.Text
import androidx.ui.graphics.ImageAsset
+import androidx.ui.graphics.vector.VectorAsset
import androidx.ui.layout.Column
+import androidx.ui.material.Checkbox
import androidx.ui.material.Divider
import androidx.ui.material.ListItem
@Sampled
@Composable
-fun OneLineListItems(icon24x24: ImageAsset, icon40x40: ImageAsset, icon56x56: ImageAsset) {
+fun OneLineListItems(
+ icon24x24: ImageAsset,
+ icon40x40: ImageAsset,
+ icon56x56: ImageAsset,
+ vectorIcon: VectorAsset
+) {
Column {
ListItem(text = "One line list item with no icon")
Divider()
@@ -43,13 +54,13 @@
Divider()
ListItem(
text = { Text("One line list item with trailing icon") },
- trailing = { Image(icon24x24) }
+ trailing = { Icon(vectorIcon) }
)
Divider()
ListItem(
text = { Text("One line list item") },
icon = { Image(icon40x40) },
- trailing = { Image(icon24x24) }
+ trailing = { Icon(vectorIcon) }
)
Divider()
}
@@ -57,6 +68,7 @@
@Sampled
@Composable
+// TODO(popam, b/159689286): material icons instead of ImageAsset when they can have custom sizes
fun TwoLineListItems(icon24x24: ImageAsset, icon40x40: ImageAsset) {
Column {
ListItem(text = "Two line list item", secondaryText = "Secondary text")
@@ -82,13 +94,13 @@
icon = icon40x40
)
Divider()
+ var checked by state { false }
ListItem(
text = { Text("Two line list item") },
secondaryText = { Text("Secondary text") },
icon = { Image(icon40x40) },
trailing = {
- // TODO(popam): put checkbox here after b/140292836 is fixed
- Image(icon24x24)
+ Checkbox(checked, onCheckedChange = { checked = !checked })
}
)
Divider()
@@ -97,7 +109,7 @@
@Sampled
@Composable
-fun ThreeLineListItems(icon24x24: ImageAsset, icon40x40: ImageAsset) {
+fun ThreeLineListItems(icon24x24: ImageAsset, vectorIcon: VectorAsset) {
Column {
ListItem(
text = "Three line list item",
@@ -126,7 +138,7 @@
secondaryText = { Text("This is a long secondary text for the current list" +
" item, displayed on two lines") },
singleLineSecondaryText = false,
- trailing = { Image(icon40x40) }
+ trailing = { Icon(vectorIcon) }
)
Divider()
ListItem(
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt
index 2ced5f6..bea103f 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SelectionControlsSamples.kt
@@ -61,7 +61,11 @@
onStateChange2(s)
}
- TriStateCheckbox(state = parentState, onClick = onParentClick, checkedColor = Color.Black)
+ TriStateCheckbox(
+ state = parentState,
+ onClick = onParentClick,
+ checkedColor = MaterialTheme.colors.primary
+ )
Column(Modifier.padding(10.dp, 0.dp, 0.dp, 0.dp)) {
Checkbox(state, onStateChange)
Checkbox(state2, onStateChange2)
diff --git a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt
index b1d57c4..8922b3c 100644
--- a/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt
+++ b/ui/ui-material/samples/src/main/java/androidx/ui/material/samples/SliderSample.kt
@@ -21,7 +21,7 @@
import androidx.compose.getValue
import androidx.compose.setValue
import androidx.compose.state
-import androidx.ui.graphics.Color
+import androidx.ui.material.MaterialTheme
import androidx.ui.material.Slider
@Sampled
@@ -40,6 +40,6 @@
onValueChange = { sliderPosition = it },
valueRange = 0f..100f,
steps = 5,
- color = Color.Black
+ color = MaterialTheme.colors.secondary
)
}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt
index beedf75..e6d6c1e 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/AppBarTest.kt
@@ -18,7 +18,6 @@
import androidx.compose.Composable
import androidx.test.filters.SmallTest
-import androidx.ui.text.LastBaseline
import androidx.ui.core.LayoutCoordinates
import androidx.ui.core.Modifier
import androidx.ui.core.globalPosition
@@ -36,7 +35,6 @@
import androidx.ui.text.TextStyle
import androidx.ui.unit.Density
import androidx.ui.unit.dp
-import androidx.ui.unit.sp
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -78,8 +76,6 @@
var appBarCoords: LayoutCoordinates? = null
var navigationIconCoords: LayoutCoordinates? = null
var titleCoords: LayoutCoordinates? = null
- // Position of the baseline relative to the top of the text
- var titleLastBaselineRelativePosition: Float? = null
var actionCoords: LayoutCoordinates? = null
composeTestRule.setMaterialContent {
Box(Modifier.onChildPositioned { appBarCoords = it }) {
@@ -88,10 +84,7 @@
FakeIcon(Modifier.onPositioned { navigationIconCoords = it })
},
title = {
- Text("title", Modifier.onPositioned { coords: LayoutCoordinates ->
- titleCoords = coords
- titleLastBaselineRelativePosition = coords[LastBaseline].toFloat()
- })
+ Text("title", Modifier.onPositioned { titleCoords = it })
},
actions = {
FakeIcon(Modifier.onPositioned { actionCoords = it })
@@ -122,13 +115,12 @@
val titleExpectedPositionX = (4.dp.toIntPx() + 68.dp.toIntPx()).toFloat()
assertThat(titlePositionX).isEqualTo(titleExpectedPositionX)
- // Absolute position of the baseline
- val titleLastBaselinePositionY = titleLastBaselineRelativePosition!! +
- titleCoords!!.globalPosition.y
- // Baseline should be 20.sp from the bottom of the app bar
- val titleExpectedLastBaselinePositionY =
- (appBarBottomEdgeY - 20.sp.toIntPx().toFloat())
- assertThat(titleLastBaselinePositionY).isEqualTo(titleExpectedLastBaselinePositionY)
+ // Title should be vertically centered
+ val titlePositionY = titleCoords!!.globalPosition.y
+ val titleHeight = titleCoords!!.size.height
+ val appBarHeight = appBarCoords!!.size.height
+ val titleExpectedPositionY = (appBarHeight - titleHeight) / 2
+ assertThat(titlePositionY).isEqualTo(titleExpectedPositionY)
// Action should be placed at the end
val actionPositionX = actionCoords!!.globalPosition.x
@@ -154,8 +146,7 @@
Box(Modifier.onChildPositioned { appBarCoords = it }) {
TopAppBar(
title = {
- Text("title",
- Modifier.onPositioned { titleCoords = it })
+ Text("title", Modifier.onPositioned { titleCoords = it })
},
actions = {
FakeIcon(Modifier.onPositioned { actionCoords = it })
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
index 9f2424b..8b5e326 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
@@ -29,11 +29,14 @@
import androidx.ui.foundation.selection.ToggleableState
import androidx.ui.layout.wrapContentSize
import androidx.ui.test.captureToBitmap
+import androidx.ui.test.center
import androidx.ui.test.createComposeRule
import androidx.ui.test.doClick
+import androidx.ui.test.doPartialGesture
import androidx.ui.test.find
import androidx.ui.test.findByTag
import androidx.ui.test.isToggleable
+import androidx.ui.test.sendDown
import androidx.ui.test.waitForIdle
import org.junit.Rule
import org.junit.Test
@@ -78,6 +81,19 @@
}
@Test
+ fun checkBoxTest_pressed() {
+ composeTestRule.setMaterialContent {
+ Box(wrap.semantics().testTag(wrapperTestTag)) {
+ Checkbox(modifier = wrap, checked = false, onCheckedChange = { })
+ }
+ }
+ findByTag(wrapperTestTag).doPartialGesture {
+ sendDown(center)
+ }
+ assertToggeableAgainstGolden("checkbox_pressed")
+ }
+
+ @Test
fun checkBoxTest_indeterminate() {
composeTestRule.setMaterialContent {
Box(wrap.semantics().testTag(wrapperTestTag)) {
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
index a5512a9..ed16c4a 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
@@ -46,7 +46,10 @@
import androidx.ui.unit.IntOffset
import androidx.ui.unit.IntSize
import androidx.ui.unit.Position
+import androidx.ui.unit.PxBounds
import androidx.ui.unit.dp
+import androidx.ui.unit.toOffset
+import androidx.ui.unit.toSize
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -234,6 +237,51 @@
}
@Test
+ fun menu_positioning_callback() {
+ val screenWidth = 500
+ val screenHeight = 1000
+ val density = Density(1f)
+ val displayMetrics = DisplayMetrics().apply {
+ widthPixels = screenWidth
+ heightPixels = screenHeight
+ }
+ val anchorPosition = IntOffset(100, 200)
+ val anchorSize = IntSize(10, 20)
+ val inset = with(density) { MenuElevation.toIntPx() }
+ val offsetX = 20
+ val offsetY = 40
+ val popupSize = IntSize(50, 80)
+
+ var obtainedParentBounds = PxBounds(0f, 0f, 0f, 0f)
+ var obtainedMenuBounds = PxBounds(0f, 0f, 0f, 0f)
+ DropdownMenuPositionProvider(
+ Position(offsetX.dp, offsetY.dp),
+ density,
+ displayMetrics
+ ) { parentBounds, menuBounds ->
+ obtainedParentBounds = parentBounds
+ obtainedMenuBounds = menuBounds
+ }.calculatePosition(
+ anchorPosition,
+ anchorSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
+
+ assertThat(obtainedParentBounds).isEqualTo(
+ PxBounds(anchorPosition.toOffset(), anchorSize.toSize())
+ )
+ assertThat(obtainedMenuBounds).isEqualTo(
+ PxBounds(
+ anchorPosition.x.toFloat() + anchorSize.width - inset + offsetX,
+ anchorPosition.y.toFloat() + anchorSize.height - inset + offsetY,
+ anchorPosition.x.toFloat() + anchorSize.width - inset + offsetX + popupSize.width,
+ anchorPosition.y.toFloat() + anchorSize.height - inset + offsetY + popupSize.height
+ )
+ )
+ }
+
+ @Test
fun dropdownMenuItem_emphasis() {
var onSurface = Color.Unset
var enabledContentColor = Color.Unset
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
index 23f5c3d..abe539d 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
@@ -29,11 +29,14 @@
import androidx.ui.foundation.Box
import androidx.ui.layout.wrapContentSize
import androidx.ui.test.captureToBitmap
+import androidx.ui.test.center
import androidx.ui.test.createComposeRule
import androidx.ui.test.doClick
+import androidx.ui.test.doPartialGesture
import androidx.ui.test.find
import androidx.ui.test.findByTag
import androidx.ui.test.isInMutuallyExclusiveGroup
+import androidx.ui.test.sendDown
import androidx.ui.test.waitForIdle
import org.junit.Rule
import org.junit.Test
@@ -78,6 +81,19 @@
}
@Test
+ fun radioButtonTest_pressed() {
+ composeTestRule.setMaterialContent {
+ Box(wrap.semantics().testTag(wrapperTestTag)) {
+ RadioButton(selected = false, onClick = {})
+ }
+ }
+ findByTag(wrapperTestTag).doPartialGesture {
+ sendDown(center)
+ }
+ assertSelectableAgainstGolden("radioButton_pressed")
+ }
+
+ @Test
fun radioButtonTest_disabled_selected() {
composeTestRule.setMaterialContent {
Box(wrap.semantics().testTag(wrapperTestTag)) {
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
index bcf3822..58317f67 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SliderTest.kt
@@ -16,21 +16,34 @@
package androidx.ui.material
+import android.os.Build
import androidx.compose.mutableStateOf
import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.ui.core.DensityAmbient
import androidx.ui.core.Modifier
import androidx.ui.core.testTag
+import androidx.ui.foundation.drawBackground
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.compositeOver
+import androidx.ui.graphics.toArgb
import androidx.ui.layout.DpConstraints
import androidx.ui.test.assertValueEquals
+import androidx.ui.test.captureToBitmap
import androidx.ui.test.createComposeRule
import androidx.ui.test.findByTag
import androidx.ui.test.runOnIdleCompose
import androidx.ui.test.runOnUiThread
import androidx.ui.unit.dp
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import kotlin.math.ceil
+import kotlin.math.floor
+import kotlin.math.sqrt
@MediumTest
@RunWith(JUnit4::class)
@@ -99,4 +112,80 @@
.assertHeightEqualsTo(48.dp)
.assertWidthEqualsTo(100.dp)
}
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun slider_endsAreRounded() {
+ val sliderTag = "slider"
+ var thumbStrokeWidth = 0
+ var thumbPx = 0
+ composeTestRule.setMaterialContent {
+ with(DensityAmbient.current) {
+ thumbStrokeWidth = TrackHeight.toIntPx()
+ thumbPx = ThumbRadius.toIntPx()
+ }
+ Slider(modifier = Modifier.testTag(sliderTag).drawBackground(Color.Gray),
+ color = Color.Green,
+ value = 0.5f,
+ onValueChange = {}
+ )
+ }
+
+ findByTag(sliderTag).captureToBitmap().apply {
+ assertNotEquals(0, thumbStrokeWidth)
+ assertNotEquals(0, thumbPx)
+
+ val compositedColor =
+ Color.Green.copy(alpha = InactiveTrackColorAlpha).compositeOver(Color.Gray)
+
+ val hyp = sqrt(2.0) / 2
+ val radius = thumbStrokeWidth / 2
+
+ val left = floor(thumbPx - radius * hyp).toInt()
+ val upper = floor(height / 2 - radius * hyp).toInt()
+ // top left outside the rounded area has the background color
+ assertEquals(getPixel(left - 1, upper - 1), Color.Gray.toArgb())
+ // top left inside the rounded area by a few pixels has the track color
+ assertEquals(getPixel(left + 3, upper + 3), Color.Green.toArgb())
+
+ val lower = ceil(height / 2 + radius * hyp).toInt()
+ // bottom left outside the rounded area has the background color
+ assertEquals(getPixel(left - 1, lower + 1), Color.Gray.toArgb())
+ // bottom left inside the rounded area by a few pixels has the track color
+ assertEquals(getPixel(left + 3, lower - 3), Color.Green.toArgb())
+
+ // top right outside the rounded area has the background color
+ val right = ceil(width - thumbPx + radius * hyp).toInt()
+ assertEquals(getPixel(right + 1, upper - 1), Color.Gray.toArgb())
+
+ // top right inside the rounded area has the track color with the
+ // inactive opacity composited over the background
+ val upperRightInsideColor = Color(getPixel(right - 3, upper + 3))
+ assertEquals(upperRightInsideColor.alpha, compositedColor.alpha, 0.01f)
+ assertEquals(upperRightInsideColor.red, compositedColor.red, 0.01f)
+ assertEquals(upperRightInsideColor.blue, compositedColor.blue, 0.01f)
+ assertEquals(upperRightInsideColor.green, compositedColor.green, 0.01f)
+
+ // lower right outside the rounded area has the background color
+ assertEquals(getPixel(right + 1, lower + 1), Color.Gray.toArgb())
+
+ // lower right inside the rounded area has the track color with the
+ // inactive opacity composited over the background
+ val lowerRightInsideColor = Color(getPixel(right - 3, lower - 3))
+ assertEquals(lowerRightInsideColor.alpha, compositedColor.alpha, 0.01f)
+ assertEquals(lowerRightInsideColor.red, compositedColor.red, 0.01f)
+ assertEquals(lowerRightInsideColor.blue, compositedColor.blue, 0.01f)
+ assertEquals(lowerRightInsideColor.green, compositedColor.green, 0.01f)
+
+ // left along the center has the track color
+ assertEquals(getPixel(thumbPx, height / 2), Color.Green.toArgb())
+
+ // right along the center has the modulated color composited over the background
+ val actualColor = Color(getPixel(width - thumbPx, height / 2))
+ assertEquals(actualColor.alpha, compositedColor.alpha, 0.01f)
+ assertEquals(actualColor.red, compositedColor.red, 0.01f)
+ assertEquals(actualColor.blue, compositedColor.blue, 0.01f)
+ assertEquals(actualColor.green, compositedColor.green, 0.01f)
+ }
+ }
}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchScreenshotTest.kt
new file mode 100644
index 0000000..6f2b19d
--- /dev/null
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchScreenshotTest.kt
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.material
+
+import android.os.Build
+import androidx.compose.state
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import androidx.test.screenshot.assertAgainstGolden
+import androidx.ui.core.Alignment
+import androidx.ui.core.Modifier
+import androidx.ui.core.testTag
+import androidx.ui.foundation.Box
+import androidx.ui.graphics.Color
+import androidx.ui.layout.wrapContentSize
+import androidx.ui.test.captureToBitmap
+import androidx.ui.test.center
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.doClick
+import androidx.ui.test.doPartialGesture
+import androidx.ui.test.find
+import androidx.ui.test.findByTag
+import androidx.ui.test.isToggleable
+import androidx.ui.test.sendDown
+import androidx.ui.test.waitForIdle
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@LargeTest
+@RunWith(JUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class SwitchScreenshotTest {
+
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @get:Rule
+ val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL)
+
+ // TODO: this test tag as well as Boxes inside testa are temporarty, remove then b/157687898
+ // is fixed
+ private val wrapperTestTag = "switchWrapper"
+
+ private val wrapperModifier = Modifier
+ .wrapContentSize(Alignment.TopStart)
+ .testTag(wrapperTestTag)
+
+ @Test
+ fun switchTest_checked() {
+ composeTestRule.setMaterialContent {
+ Box(wrapperModifier) {
+ Switch(checked = true, onCheckedChange = { })
+ }
+ }
+ assertToggeableAgainstGolden("switch_checked")
+ }
+
+ @Test
+ fun switchTest_checked_customColor() {
+ composeTestRule.setMaterialContent {
+ Box(wrapperModifier) {
+ Switch(checked = true, onCheckedChange = { }, color = Color.Red)
+ }
+ }
+ assertToggeableAgainstGolden("switch_checked_customColor")
+ }
+
+ @Test
+ fun switchTest_unchecked() {
+ composeTestRule.setMaterialContent {
+ Box(wrapperModifier) {
+ Switch(checked = false, onCheckedChange = { })
+ }
+ }
+ assertToggeableAgainstGolden("switch_unchecked")
+ }
+
+ @Test
+ fun switchTest_pressed() {
+ composeTestRule.setMaterialContent {
+ Box(wrapperModifier) {
+ Switch(checked = false, enabled = true, onCheckedChange = { })
+ }
+ }
+
+ findByTag(wrapperTestTag).doPartialGesture {
+ sendDown(center)
+ }
+ assertToggeableAgainstGolden("switch_pressed")
+ }
+
+ @Test
+ fun switchTest_disabled_checked() {
+ composeTestRule.setMaterialContent {
+ Box(wrapperModifier) {
+ Switch(checked = true, enabled = false, onCheckedChange = { })
+ }
+ }
+ assertToggeableAgainstGolden("switch_disabled_checked")
+ }
+
+ @Test
+ fun switchTest_disabled_unchecked() {
+ composeTestRule.setMaterialContent {
+ Box(wrapperModifier) {
+ Switch(checked = false, enabled = false, onCheckedChange = { })
+ }
+ }
+ assertToggeableAgainstGolden("switch_disabled_unchecked")
+ }
+
+ @Test
+ fun switchTest_unchecked_animateToChecked() {
+ composeTestRule.setMaterialContent {
+ val isChecked = state { false }
+ Box(wrapperModifier) {
+ Switch(
+ checked = isChecked.value,
+ onCheckedChange = { isChecked.value = it }
+ )
+ }
+ }
+
+ composeTestRule.clockTestRule.pauseClock()
+
+ find(isToggleable())
+ .doClick()
+
+ waitForIdle()
+
+ composeTestRule.clockTestRule.advanceClock(60)
+
+ assertToggeableAgainstGolden("switch_animateToChecked")
+ }
+
+ @Test
+ fun switchTest_checked_animateToUnchecked() {
+ composeTestRule.setMaterialContent {
+ val isChecked = state { true }
+ Box(wrapperModifier) {
+ Switch(
+ checked = isChecked.value,
+ onCheckedChange = { isChecked.value = it }
+ )
+ }
+ }
+
+ composeTestRule.clockTestRule.pauseClock()
+
+ find(isToggleable())
+ .doClick()
+
+ waitForIdle()
+
+ composeTestRule.clockTestRule.advanceClock(60)
+
+ assertToggeableAgainstGolden("switch_animateToUnchecked")
+ }
+
+ private fun assertToggeableAgainstGolden(goldenName: String) {
+ // TODO: replace with find(isToggeable()) after b/157687898 is fixed
+ findByTag(wrapperTestTag)
+ .captureToBitmap()
+ .assertAgainstGolden(screenshotRule, goldenName)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchUiTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchTest.kt
similarity index 99%
rename from ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchUiTest.kt
rename to ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchTest.kt
index 20ac970..9767264 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchUiTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/SwitchTest.kt
@@ -39,7 +39,7 @@
@MediumTest
@RunWith(JUnit4::class)
-class SwitchUiTest {
+class SwitchTest {
@get:Rule
val composeTestRule = createComposeRule(disableTransitions = true)
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt
index d59924b..24f5c3f 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/TabTest.kt
@@ -20,11 +20,8 @@
import androidx.compose.setValue
import androidx.compose.state
import androidx.test.filters.LargeTest
-import androidx.ui.text.LastBaseline
-import androidx.ui.core.LayoutCoordinates
import androidx.ui.core.Modifier
-import androidx.ui.core.onChildPositioned
-import androidx.ui.core.onPositioned
+import androidx.ui.core.testTag
import androidx.ui.foundation.Box
import androidx.ui.foundation.Icon
import androidx.ui.foundation.Text
@@ -32,7 +29,6 @@
import androidx.ui.graphics.Color
import androidx.ui.layout.fillMaxWidth
import androidx.ui.layout.preferredHeight
-import androidx.ui.layout.preferredWidth
import androidx.ui.material.icons.Icons
import androidx.ui.material.icons.filled.Favorite
import androidx.ui.material.samples.ScrollingTextTabs
@@ -40,13 +36,18 @@
import androidx.ui.test.assertCountEquals
import androidx.ui.test.assertIsSelected
import androidx.ui.test.assertIsUnselected
+import androidx.ui.test.assertPositionInRootIsEqualTo
import androidx.ui.test.createComposeRule
import androidx.ui.test.doClick
import androidx.ui.test.findAll
+import androidx.ui.test.findByTag
+import androidx.ui.test.getAlignmentLinePosition
+import androidx.ui.test.getBoundsInRoot
import androidx.ui.test.isInMutuallyExclusiveGroup
-import androidx.ui.test.runOnIdleCompose
-import androidx.ui.geometry.Offset
+import androidx.ui.text.LastBaseline
import androidx.ui.unit.dp
+import androidx.ui.unit.height
+import androidx.ui.unit.width
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -108,8 +109,6 @@
@Test
fun fixedTabRow_indicatorPosition() {
val indicatorHeight = 1.dp
- lateinit var tabRowCoords: LayoutCoordinates
- lateinit var indicatorCoords: LayoutCoordinates
composeTestRule.setMaterialContent {
var state by state { 0 }
@@ -118,15 +117,15 @@
val indicatorContainer = @Composable { tabPositions: List<TabRow.TabPosition> ->
TabRow.IndicatorContainer(tabPositions, state) {
Box(Modifier
- .onPositioned { indicatorCoords = it }
.fillMaxWidth()
.preferredHeight(indicatorHeight)
.drawBackground(Color.Red)
+ .testTag("indicator")
)
}
}
- Box(Modifier.onChildPositioned { tabRowCoords = it }) {
+ Box(Modifier.testTag("tabRow")) {
TabRow(
items = titles,
selectedIndex = state,
@@ -141,62 +140,41 @@
}
}
- val (tabRowWidth, tabRowHeight) = composeTestRule.runOnIdleComposeWithDensity {
- val tabRowWidth = tabRowCoords.size.width
- val tabRowHeight = tabRowCoords.size.height
+ val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
- val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
- val expectedPositionX = 0.dp.toPx()
- assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
- val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
- val expectedPositionY = (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
- assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
-
- tabRowWidth to tabRowHeight
- }
+ findByTag("indicator")
+ .assertPositionInRootIsEqualTo(
+ expectedLeft = 0.dp,
+ expectedTop = tabRowBounds.height - indicatorHeight
+ )
// Click the second tab
findAll(isInMutuallyExclusiveGroup())[1].doClick()
// Indicator should now be placed in the bottom left of the second tab, so its x coordinate
// should be in the middle of the TabRow
- runOnIdleCompose {
- with(composeTestRule.density) {
- val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
- val expectedPositionX = (tabRowWidth / 2).toFloat()
- assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
- val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
- val expectedPositionY =
- (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
- assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
- }
- }
+ findByTag("indicator")
+ .assertPositionInRootIsEqualTo(
+ expectedLeft = (tabRowBounds.width / 2),
+ expectedTop = tabRowBounds.height - indicatorHeight
+ )
}
@Test
fun singleLineTab_textBaseline() {
- lateinit var tabRowCoords: LayoutCoordinates
- lateinit var textCoords: LayoutCoordinates
- var textBaseline = Float.NEGATIVE_INFINITY
-
composeTestRule.setMaterialContent {
var state by state { 0 }
val titles = listOf("TAB")
Box {
TabRow(
- modifier = Modifier.onPositioned { tabRowCoords = it },
+ modifier = Modifier.testTag("tabRow"),
items = titles,
selectedIndex = state
) { index, text ->
Tab(
text = {
- Text(text, Modifier.onPositioned { coords: LayoutCoordinates ->
- textCoords = coords
- textBaseline = coords[LastBaseline].toFloat()
- })
+ Text(text, Modifier.testTag("text"))
},
selected = state == index,
onSelected = { state = index }
@@ -205,43 +183,35 @@
}
}
- composeTestRule.runOnIdleComposeWithDensity {
- val expectedBaseline = 18.dp
- val indicatorHeight = 2.dp
- val expectedBaselineDistance =
- (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toFloat()
+ val expectedBaseline = 18.dp
+ val indicatorHeight = 2.dp
+ val expectedBaselineDistance = expectedBaseline + indicatorHeight
- val tabRowHeight = tabRowCoords.size.height
+ val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
+ val textBounds = findByTag("text").getBoundsInRoot()
+ val textBaselinePos = findByTag("text").getAlignmentLinePosition(LastBaseline)
- val textPositionY = textCoords.localToGlobal(Offset.Zero).y
- val baselinePositionY = textPositionY + textBaseline
- val expectedPositionY = (tabRowHeight.toFloat() - expectedBaselineDistance)
- assertThat(baselinePositionY).isEqualTo(expectedPositionY)
- }
+ val baselinePositionY = textBounds.top + textBaselinePos
+ val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
+
+ assertThat(baselinePositionY.value).isWithin(0.5f).of(expectedPositionY.value)
}
@Test
fun singleLineTab_withIcon_textBaseline() {
- lateinit var tabRowCoords: LayoutCoordinates
- lateinit var textCoords: LayoutCoordinates
- var textBaseline = Float.NEGATIVE_INFINITY
-
composeTestRule.setMaterialContent {
var state by state { 0 }
val titles = listOf("TAB")
Box {
TabRow(
- modifier = Modifier.onPositioned { tabRowCoords = it },
+ modifier = Modifier.testTag("tabRow"),
items = titles,
selectedIndex = state
) { index, text ->
Tab(
text = {
- Text(text, Modifier.onPositioned { coords: LayoutCoordinates ->
- textCoords = coords
- textBaseline = coords[LastBaseline].toFloat()
- })
+ Text(text, Modifier.testTag("text"))
},
icon = { Icon(Icons.Filled.Favorite) },
selected = state == index,
@@ -251,43 +221,34 @@
}
}
- composeTestRule.runOnIdleComposeWithDensity {
- val expectedBaseline = 14.dp
- val indicatorHeight = 2.dp
- val expectedBaselineDistance =
- (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toFloat()
+ val expectedBaseline = 14.dp
+ val indicatorHeight = 2.dp
+ val expectedBaselineDistance = expectedBaseline + indicatorHeight
- val tabRowHeight = tabRowCoords.size.height
+ val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
+ val textBounds = findByTag("text").getBoundsInRoot()
+ val textBaselinePos = findByTag("text").getAlignmentLinePosition(LastBaseline)
- val textPositionY = textCoords.localToGlobal(Offset.Zero).y
- val baselinePositionY = textPositionY + textBaseline
- val expectedPositionY = (tabRowHeight.toFloat() - expectedBaselineDistance)
- assertThat(baselinePositionY).isEqualTo(expectedPositionY)
- }
+ val baselinePositionY = textBounds.top + textBaselinePos
+ val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
+ assertThat(baselinePositionY).isEqualTo(expectedPositionY)
}
@Test
fun twoLineTab_textBaseline() {
- lateinit var tabRowCoords: LayoutCoordinates
- lateinit var textCoords: LayoutCoordinates
- var textBaseline = Float.NEGATIVE_INFINITY
-
composeTestRule.setMaterialContent {
var state by state { 0 }
val titles = listOf("VERY LONG TAB TITLE THAT WILL BE FORCED TO GO TO TWO LINES")
Box {
TabRow(
- modifier = Modifier.onPositioned { tabRowCoords = it },
+ modifier = Modifier.testTag("tabRow"),
items = titles,
selectedIndex = state
) { index, text ->
Tab(
text = {
- Text(text, Modifier.preferredWidth(100.dp).onPositioned { coords ->
- textCoords = coords
- textBaseline = coords[LastBaseline].toFloat()
- }, maxLines = 2)
+ Text(text, Modifier.testTag("text"), maxLines = 2)
},
selected = state == index,
onSelected = { state = index }
@@ -296,19 +257,18 @@
}
}
- composeTestRule.runOnIdleComposeWithDensity {
- val expectedBaseline = 10.dp
- val indicatorHeight = 2.dp
- val expectedBaselineDistance =
- (expectedBaseline.toIntPx() + indicatorHeight.toIntPx()).toFloat()
+ val expectedBaseline = 10.dp
+ val indicatorHeight = 2.dp
- val tabRowHeight = tabRowCoords.size.height
+ val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
+ val textBounds = findByTag("text").getBoundsInRoot()
+ val textBaselinePos = findByTag("text").getAlignmentLinePosition(LastBaseline)
- val textPositionY = textCoords.localToGlobal(Offset.Zero).y
- val baselinePositionY = textPositionY + textBaseline
- val expectedPositionY = (tabRowHeight.toFloat() - expectedBaselineDistance)
- assertThat(baselinePositionY).isEqualTo(expectedPositionY)
- }
+ val expectedBaselineDistance = expectedBaseline + indicatorHeight
+
+ val baselinePositionY = textBounds.top + textBaselinePos
+ val expectedPositionY = (tabRowBounds.height - expectedBaselineDistance)
+ assertThat(baselinePositionY.value).isWithin(0.5f).of(expectedPositionY.value)
}
@Test
@@ -316,8 +276,6 @@
val indicatorHeight = 1.dp
val scrollableTabRowOffset = 52.dp
val minimumTabWidth = 90.dp
- lateinit var tabRowCoords: LayoutCoordinates
- lateinit var indicatorCoords: LayoutCoordinates
composeTestRule.setMaterialContent {
var state by state { 0 }
@@ -326,17 +284,17 @@
val indicatorContainer = @Composable { tabPositions: List<TabRow.TabPosition> ->
TabRow.IndicatorContainer(tabPositions, state) {
Box(Modifier
- .onPositioned { indicatorCoords = it }
.fillMaxWidth()
.preferredHeight(indicatorHeight)
.drawBackground(Color.Red)
+ .testTag("indicator")
)
}
}
Box {
TabRow(
- modifier = Modifier.onPositioned { tabRowCoords = it },
+ modifier = Modifier.testTag("tabRow"),
items = titles,
scrollable = true,
selectedIndex = state,
@@ -351,38 +309,26 @@
}
}
- val tabRowHeight = composeTestRule.runOnIdleComposeWithDensity {
- val tabRowHeight = tabRowCoords.size.height
+ val tabRowBounds = findByTag("tabRow").getBoundsInRoot()
- // Indicator should be placed in the bottom left of the first tab
- val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
- // Tabs in a scrollable tab row are offset 52.dp from each end
- val expectedPositionX = scrollableTabRowOffset.toIntPx().toFloat()
- assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
- val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
- val expectedPositionY = (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
- assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
-
- tabRowHeight
- }
+ // Indicator should be placed in the bottom left of the first tab
+ findByTag("indicator")
+ .assertPositionInRootIsEqualTo(
+ // Tabs in a scrollable tab row are offset 52.dp from each end
+ expectedLeft = scrollableTabRowOffset,
+ expectedTop = tabRowBounds.height - indicatorHeight
+ )
// Click the second tab
findAll(isInMutuallyExclusiveGroup())[1].doClick()
// Indicator should now be placed in the bottom left of the second tab, so its x coordinate
// should be in the middle of the TabRow
- composeTestRule.runOnIdleComposeWithDensity {
- val indicatorPositionX = indicatorCoords.localToGlobal(Offset.Zero).x
- val expectedPositionX =
- (scrollableTabRowOffset + minimumTabWidth).toIntPx().toFloat()
- assertThat(indicatorPositionX).isEqualTo(expectedPositionX)
-
- val indicatorPositionY = indicatorCoords.localToGlobal(Offset.Zero).y
- val expectedPositionY =
- (tabRowHeight - indicatorHeight.toIntPx()).toFloat()
- assertThat(indicatorPositionY).isEqualTo(expectedPositionY)
- }
+ findByTag("indicator")
+ .assertPositionInRootIsEqualTo(
+ expectedLeft = scrollableTabRowOffset + minimumTabWidth,
+ expectedTop = tabRowBounds.height - indicatorHeight
+ )
}
@Test
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
new file mode 100644
index 0000000..38893bc
--- /dev/null
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.material.textfield
+
+import android.os.Build
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import androidx.test.screenshot.assertAgainstGolden
+import androidx.ui.core.Modifier
+import androidx.ui.core.semantics.semantics
+import androidx.ui.core.testTag
+import androidx.ui.foundation.Box
+import androidx.ui.foundation.Text
+import androidx.ui.layout.rtl
+import androidx.ui.material.FilledTextField
+import androidx.ui.material.GOLDEN_MATERIAL
+import androidx.ui.material.OutlinedTextField
+import androidx.ui.material.setMaterialContent
+import androidx.ui.test.captureToBitmap
+import androidx.ui.test.createComposeRule
+import androidx.ui.test.doClick
+import androidx.ui.test.findByTag
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@LargeTest
+@RunWith(JUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+class TextFieldScreenshotTest {
+
+ private val TextFieldTag = "textField"
+
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @get:Rule
+ val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL)
+
+ @Test
+ fun outlinedTextField_withInput() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+ OutlinedTextField(
+ value = "Text",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ assertAgainstGolden("outlined_textField_withInput")
+ }
+
+ @Test
+ fun outlinedTextField_notFocused() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+ OutlinedTextField(
+ value = "",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ assertAgainstGolden("outlined_textField_not_focused")
+ }
+
+ @Test
+ fun outlinedTextField_focused() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+ OutlinedTextField(
+ value = "",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ findByTag(TextFieldTag)
+ .doClick()
+
+ assertAgainstGolden("outlined_textField_focused")
+ }
+
+ @Test
+ fun outlinedTextField_focused_rtl() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag).rtl) {
+ OutlinedTextField(
+ value = "",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ findByTag(TextFieldTag)
+ .doClick()
+
+ assertAgainstGolden("outlined_textField_focused_rtl")
+ }
+
+ @Test
+ fun filledTextField_withInput() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+ FilledTextField(
+ value = "Text",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ assertAgainstGolden("filled_textField_withInput")
+ }
+
+ @Test
+ fun filledTextField_notFocused() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+ FilledTextField(
+ value = "",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ assertAgainstGolden("filled_textField_not_focused")
+ }
+
+ @Test
+ fun filledTextField_focused() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag)) {
+ FilledTextField(
+ value = "",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ findByTag(TextFieldTag)
+ .doClick()
+
+ assertAgainstGolden("filled_textField_focused")
+ }
+
+ @Test
+ fun filledTextField_focused_rtl() {
+ composeTestRule.setMaterialContent {
+ Box(Modifier.semantics(mergeAllDescendants = true).testTag(TextFieldTag).rtl) {
+ FilledTextField(
+ value = "",
+ onValueChange = {},
+ label = { Text("Label") }
+ )
+ }
+ }
+
+ findByTag(TextFieldTag)
+ .doClick()
+
+ assertAgainstGolden("filled_textField_focused_rtl")
+ }
+
+ private fun assertAgainstGolden(goldenIdentifier: String) {
+ findByTag(TextFieldTag)
+ .captureToBitmap()
+ .assertAgainstGolden(screenshotRule, goldenIdentifier)
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/TextFieldTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldTest.kt
similarity index 95%
rename from ui/ui-material/src/androidTest/java/androidx/ui/material/TextFieldTest.kt
rename to ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldTest.kt
index d6a91b9..bee20c7 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/TextFieldTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldTest.kt
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-package androidx.ui.material
+package androidx.ui.material.textfield
import android.os.Build
import androidx.compose.Providers
-import androidx.compose.getValue
import androidx.compose.remember
-import androidx.compose.setValue
import androidx.compose.state
import androidx.test.filters.MediumTest
import androidx.test.filters.SdkSuppress
@@ -84,6 +82,14 @@
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
import androidx.ui.layout.preferredWidth
+import androidx.ui.material.FilledTextField
+import androidx.ui.material.MaterialTheme
+import androidx.ui.material.OutlinedTextField
+import androidx.ui.material.TextFieldScroller
+import androidx.ui.material.TextFieldScrollerPosition
+import androidx.ui.material.runOnIdleComposeWithDensity
+import androidx.ui.material.setMaterialContent
+import androidx.ui.material.setMaterialContentAndCollectSizes
@MediumTest
@RunWith(JUnit4::class)
@@ -728,7 +734,11 @@
placeholder = {
Text("placeholder")
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(0.6f))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ 0.6f
+ )
+ )
assertThat(currentTextStyle()).isEqualTo(MaterialTheme.typography.subtitle1)
}
)
@@ -749,7 +759,11 @@
placeholder = {
Text("placeholder")
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(0.6f))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ 0.6f
+ )
+ )
assertThat(currentTextStyle()).isEqualTo(MaterialTheme.typography.subtitle1)
}
)
@@ -985,11 +999,19 @@
isErrorValue = false,
leadingIcon = {
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ IconColorAlpha
+ )
+ )
},
trailingIcon = {
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ IconColorAlpha
+ )
+ )
}
)
OutlinedTextField(
@@ -999,11 +1021,19 @@
isErrorValue = false,
leadingIcon = {
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ IconColorAlpha
+ )
+ )
},
trailingIcon = {
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ IconColorAlpha
+ )
+ )
}
)
}
@@ -1021,7 +1051,11 @@
isErrorValue = true,
leadingIcon = {
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ IconColorAlpha
+ )
+ )
},
trailingIcon = {
assertThat(contentColor()).isEqualTo(MaterialTheme.colors.error)
@@ -1034,7 +1068,11 @@
isErrorValue = true,
leadingIcon = {
assertThat(contentColor())
- .isEqualTo(MaterialTheme.colors.onSurface.copy(IconColorAlpha))
+ .isEqualTo(
+ MaterialTheme.colors.onSurface.copy(
+ IconColorAlpha
+ )
+ )
},
trailingIcon = {
assertThat(contentColor()).isEqualTo(MaterialTheme.colors.error)
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt b/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
index 660fbaa..f5e0760 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
@@ -16,10 +16,8 @@
package androidx.ui.material
import androidx.compose.Composable
-import androidx.ui.core.DensityAmbient
import androidx.ui.core.Modifier
import androidx.ui.core.semantics.semantics
-import androidx.ui.foundation.Box
import androidx.ui.foundation.ContentGravity
import androidx.ui.foundation.ProvideTextStyle
import androidx.ui.foundation.shape.corner.CircleShape
@@ -43,14 +41,11 @@
import androidx.ui.layout.padding
import androidx.ui.layout.preferredHeight
import androidx.ui.layout.preferredWidth
-import androidx.ui.layout.relativePaddingFrom
-import androidx.ui.text.LastBaseline
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
import androidx.ui.unit.PxBounds
import androidx.ui.unit.dp
import androidx.ui.unit.height
-import androidx.ui.unit.sp
import androidx.ui.unit.width
import kotlin.math.sqrt
@@ -58,8 +53,10 @@
* A TopAppBar displays information and actions relating to the current screen and is placed at the
* top of the screen.
*
- * This TopAppBar has slots for a title, navigation icon, and actions. Use the other TopAppBar
- * overload for a generic TopAppBar with no restriction on content.
+ * This TopAppBar has slots for a title, navigation icon, and actions. Note that the [title] slot
+ * is inset from the start according to spec - for custom use cases such as horizontally
+ * centering the title, use the other TopAppBar overload for a generic TopAppBar with no
+ * restriction on content.
*
* @sample androidx.ui.material.samples.SimpleTopAppBar
*
@@ -95,12 +92,12 @@
}
}
- Box(Modifier.fillMaxHeight().weight(1f).semantics(), gravity = ContentGravity.BottomStart) {
+ Row(
+ Modifier.fillMaxHeight().weight(1f).semantics(),
+ verticalGravity = ContentGravity.CenterVertically
+ ) {
ProvideTextStyle(value = MaterialTheme.typography.h6) {
- val baselineOffset = with(DensityAmbient.current) { TitleBaselineOffset.toDp() }
- Row(Modifier.relativePaddingFrom(LastBaseline, after = baselineOffset)) {
- ProvideEmphasis(emphasisLevels.high, title)
- }
+ ProvideEmphasis(emphasisLevels.high, title)
}
}
@@ -463,8 +460,6 @@
// Start inset for the title when there is a navigation icon provided
private val TitleIconModifier = Modifier.fillMaxHeight()
.preferredWidth(72.dp - AppBarHorizontalPadding)
-// The baseline distance for the title from the bottom of the app bar
-private val TitleBaselineOffset = 20.sp
private val BottomAppBarElevation = 8.dp
// TODO: clarify elevation in surface mapping - spec says 0.dp but it appears to have an
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt b/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt
index 927aa89..21a9535 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Checkbox.kt
@@ -131,7 +131,7 @@
state = state,
onClick = onClick,
enabled = enabled,
- indication = RippleIndication(bounded = false)
+ indication = RippleIndication(bounded = false, radius = CheckboxRippleRadius)
)
.padding(CheckboxDefaultPadding),
enabled = enabled,
@@ -362,6 +362,7 @@
}
}
+private val CheckboxRippleRadius = 24.dp
private val CheckboxDefaultPadding = 2.dp
private val CheckboxSize = 20.dp
private val StrokeWidth = 2.dp
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt b/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
index 3d11dcd..e420d35 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
@@ -23,17 +23,19 @@
import androidx.compose.Composable
import androidx.compose.Immutable
import androidx.compose.getValue
+import androidx.compose.remember
import androidx.compose.setValue
import androidx.compose.state
import androidx.ui.animation.Transition
import androidx.ui.core.ContextAmbient
import androidx.ui.core.DensityAmbient
+import androidx.ui.core.DrawLayerModifier
import androidx.ui.core.LayoutDirection
import androidx.ui.core.Modifier
import androidx.ui.core.Popup
import androidx.ui.core.PopupPositionProvider
+import androidx.ui.core.TransformOrigin
import androidx.ui.unit.Position
-import androidx.ui.core.drawLayer
import androidx.ui.foundation.Box
import androidx.ui.foundation.ContentGravity
import androidx.ui.foundation.ProvideTextStyle
@@ -50,7 +52,15 @@
import androidx.ui.unit.Density
import androidx.ui.unit.IntOffset
import androidx.ui.unit.IntSize
+import androidx.ui.unit.PxBounds
import androidx.ui.unit.dp
+import androidx.ui.unit.height
+import androidx.ui.unit.toOffset
+import androidx.ui.unit.toSize
+import androidx.ui.unit.width
+import kotlin.math.max
+import kotlin.math.min
+
/**
* A Material Design [dropdown menu](https://material.io/components/menus#dropdown-menu).
*
@@ -94,11 +104,15 @@
toggle()
if (visibleMenu) {
+ var transformOrigin by state { TransformOrigin.Center }
+ val density = DensityAmbient.current
val popupPositionProvider = DropdownMenuPositionProvider(
dropdownOffset,
- DensityAmbient.current,
+ density,
ContextAmbient.current.resources.displayMetrics
- )
+ ) { parentBounds, menuBounds ->
+ transformOrigin = calculateTransformOrigin(parentBounds, menuBounds, density)
+ }
Popup(
isFocusable = true,
@@ -113,18 +127,22 @@
visibleMenu = it
}
) { state ->
- val scale = state[Scale]
- val alpha = state[Alpha]
+ val drawLayer = remember {
+ MenuDrawLayerModifier(
+ { state[Scale] },
+ { state[Alpha] },
+ { transformOrigin }
+ )
+ }
Card(
- modifier = Modifier
- .drawLayer(scaleX = scale, scaleY = scale, alpha = alpha, clip = true)
+ modifier = drawLayer
// Padding to account for the elevation, otherwise it is clipped.
.padding(MenuElevation),
elevation = MenuElevation
) {
@OptIn(ExperimentalLayout::class)
Column(
- dropdownModifier
+ modifier = dropdownModifier
.padding(vertical = DropdownMenuVerticalPadding)
.preferredWidth(IntrinsicSize.Max),
children = dropdownContent
@@ -197,7 +215,7 @@
private val DropdownMenuOpenCloseTransition = transitionDefinition {
state(false) {
// Menu is dismissed.
- this[Scale] = 0f
+ this[Scale] = 0.8f
this[Alpha] = 0f
}
state(true) {
@@ -227,6 +245,53 @@
}
}
+private class MenuDrawLayerModifier(
+ val scaleProvider: () -> Float,
+ val alphaProvider: () -> Float,
+ val transformOriginProvider: () -> TransformOrigin
+) : DrawLayerModifier {
+ override val scaleX: Float get() = scaleProvider()
+ override val scaleY: Float get() = scaleProvider()
+ override val alpha: Float get() = alphaProvider()
+ override val transformOrigin: TransformOrigin get() = transformOriginProvider()
+ override val clip: Boolean = true
+}
+
+private fun calculateTransformOrigin(
+ parentBounds: PxBounds,
+ menuBounds: PxBounds,
+ density: Density
+): TransformOrigin {
+ val inset = with(density) { MenuElevation.toPx() }
+ val realMenuBounds = PxBounds(
+ menuBounds.left + inset,
+ menuBounds.top + inset,
+ menuBounds.right - inset,
+ menuBounds.bottom - inset
+ )
+ val pivotX = when {
+ realMenuBounds.left >= parentBounds.right -> 0f
+ realMenuBounds.right <= parentBounds.left -> 1f
+ else -> {
+ val intersectionCenter =
+ (max(parentBounds.left, realMenuBounds.left) +
+ min(parentBounds.right, realMenuBounds.right)) / 2
+ (intersectionCenter + inset - menuBounds.left) / menuBounds.width
+ }
+ }
+ val pivotY = when {
+ realMenuBounds.top >= parentBounds.bottom -> 0f
+ realMenuBounds.bottom <= parentBounds.top -> 1f
+ else -> {
+ val intersectionCenter =
+ (max(parentBounds.top, realMenuBounds.top) +
+ min(parentBounds.bottom, realMenuBounds.bottom)) / 2
+ (intersectionCenter + inset - menuBounds.top) / menuBounds.height
+ }
+ }
+ return TransformOrigin(pivotX, pivotY)
+}
+
// Menu positioning.
/**
@@ -237,7 +302,8 @@
internal data class DropdownMenuPositionProvider(
val contentOffset: Position,
val density: Density,
- val displayMetrics: DisplayMetrics
+ val displayMetrics: DisplayMetrics,
+ val onPositionCalculated: (PxBounds, PxBounds) -> Unit = { _, _ -> }
) : PopupPositionProvider {
override fun calculatePosition(
parentLayoutPosition: IntOffset,
@@ -276,6 +342,16 @@
it >= 0 && it + realPopupHeight <= displayMetrics.heightPixels
} ?: toTop
+ // TODO(popam, b/159596546): we should probably have androidx.ui.unit.IntBounds instead
+ onPositionCalculated(
+ PxBounds(parentLayoutPosition.toOffset(), parentLayoutSize.toSize()),
+ PxBounds(
+ x.toFloat() - inset,
+ y.toFloat() - inset,
+ x.toFloat() + inset + realPopupWidth,
+ y.toFloat() + inset + realPopupHeight
+ )
+ )
return IntOffset(x - inset, y - inset)
}
}
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt b/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt
index 41a3ffe..ed96e0c 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/RadioButton.kt
@@ -339,7 +339,7 @@
selected = selected,
onClick = onClick,
enabled = enabled,
- indication = RippleIndication(bounded = false)
+ indication = RippleIndication(bounded = false, radius = RadioButtonRippleRadius)
)
.wrapContentSize(Alignment.Center)
.padding(RadioButtonPadding)
@@ -409,6 +409,7 @@
}
}
+private val RadioButtonRippleRadius = 24.dp
private val RadioButtonPadding = 2.dp
private val RadioButtonSize = 20.dp
private val RadioRadius = RadioButtonSize / 2
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt b/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt
index df8fec0..8425445 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Slider.kt
@@ -254,7 +254,7 @@
center.y
)
- drawLine(color, sliderStart, sliderValue, trackStrokeWidth)
+ drawLine(color, sliderStart, sliderValue, trackStrokeWidth, StrokeCap.round)
tickFractions.groupBy { it > positionFraction }.forEach { (afterFraction, list) ->
drawPoints(
list.map {
@@ -262,7 +262,8 @@
},
PointMode.points,
if (afterFraction) inactiveTickColor else activeTickColor,
- trackStrokeWidth
+ trackStrokeWidth,
+ StrokeCap.round
)
}
}
@@ -451,16 +452,21 @@
}
}
-private val ThumbRadius = 10.dp
+// Internal to be referred to in tests
+internal val ThumbRadius = 10.dp
private val ThumbRippleRadius = 24.dp
private val ThumbDefaultElevation = 1.dp
private val ThumbPressedElevation = 6.dp
-private val TrackHeight = 4.dp
+
+// Internal to be referred to in tests
+internal val TrackHeight = 4.dp
private val SliderHeight = 48.dp
private val SliderMinWidth = 144.dp // TODO: clarify min width
private val DefaultSliderConstraints =
Modifier.preferredWidthIn(minWidth = SliderMinWidth)
.preferredHeightIn(maxHeight = SliderHeight)
-private val InactiveTrackColorAlpha = 0.24f
+
+// Internal to be referred to in tests
+internal val InactiveTrackColorAlpha = 0.24f
private val TickColorAlpha = 0.54f
private val SliderToTickAnimation = TweenBuilder<Float>().apply { duration = 100 }
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt b/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt
index ba5f936..fa43067 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Switch.kt
@@ -19,20 +19,35 @@
import androidx.animation.TweenBuilder
import androidx.compose.Composable
import androidx.compose.State
+import androidx.compose.remember
import androidx.compose.state
+import androidx.ui.core.Alignment
import androidx.ui.core.DensityAmbient
import androidx.ui.core.Modifier
import androidx.ui.core.semantics.semantics
-import androidx.ui.foundation.Box
import androidx.ui.foundation.Canvas
+import androidx.ui.foundation.Interaction
+import androidx.ui.foundation.InteractionState
import androidx.ui.foundation.gestures.DragDirection
+import androidx.ui.foundation.indication
import androidx.ui.foundation.selection.toggleable
+import androidx.ui.foundation.shape.corner.CircleShape
import androidx.ui.geometry.Offset
import androidx.ui.graphics.Color
import androidx.ui.graphics.StrokeCap
+import androidx.ui.graphics.compositeOver
import androidx.ui.graphics.drawscope.DrawScope
+import androidx.ui.layout.Stack
+import androidx.ui.layout.StackScope
+import androidx.ui.layout.offsetPx
import androidx.ui.layout.padding
import androidx.ui.layout.preferredSize
+import androidx.ui.material.SwitchDefaults.disabledUncheckedThumbColor
+import androidx.ui.material.SwitchDefaults.disabledUncheckedTrackColor
+import androidx.ui.material.SwitchDefaults.makeDisabledCheckedThumbColor
+import androidx.ui.material.SwitchDefaults.makeDisabledCheckedTrackColor
+import androidx.ui.material.SwitchDefaults.uncheckedThumbColor
+import androidx.ui.material.SwitchDefaults.uncheckedTrackColor
import androidx.ui.material.internal.stateDraggable
import androidx.ui.material.ripple.RippleIndication
import androidx.ui.unit.dp
@@ -47,7 +62,7 @@
* therefore the change of checked state is requested.
* @param modifier Modifier to be applied to the switch layout
* @param enabled whether or not components is enabled and can be clicked to request state change
- * @param color active color for Switch
+ * @param color main color of the track and trumb when the Switch is checked
*/
@Composable
fun Switch(
@@ -60,14 +75,16 @@
val minBound = 0f
val maxBound = with(DensityAmbient.current) { ThumbPathLength.toPx() }
val thumbPosition = state { if (checked) maxBound else minBound }
- Box(
+ val interactionState = remember { InteractionState() }
+ Stack(
modifier
.semantics(mergeAllDescendants = true)
.toggleable(
value = checked,
onValueChange = onCheckedChange,
enabled = enabled,
- indication = RippleIndication(bounded = false)
+ interactionState = interactionState,
+ indication = null
)
.stateDraggable(
state = checked,
@@ -77,35 +94,56 @@
dragDirection = DragDirection.Horizontal,
minValue = minBound,
maxValue = maxBound,
+ enabled = enabled,
+ interactionState = interactionState,
onNewValue = { thumbPosition.value = it }
)
.padding(DefaultSwitchPadding)
) {
- DrawSwitch(
+ SwitchImpl(
checked = checked,
- checkedThumbColor = color,
- thumbValue = thumbPosition
+ enabled = enabled,
+ checkedColor = color,
+ thumbValue = thumbPosition,
+ interactionState = interactionState
)
}
}
@Composable
-private fun DrawSwitch(
+private fun StackScope.SwitchImpl(
checked: Boolean,
- checkedThumbColor: Color,
- thumbValue: State<Float>
+ enabled: Boolean,
+ checkedColor: Color,
+ thumbValue: State<Float>,
+ interactionState: InteractionState
) {
- val thumbColor = if (checked) checkedThumbColor else MaterialTheme.colors.surface
- val trackColor = if (checked) {
- checkedThumbColor.copy(alpha = CheckedTrackOpacity)
- } else {
- MaterialTheme.colors.onSurface.copy(alpha = UncheckedTrackOpacity)
- }
-
- Canvas(Modifier.preferredSize(SwitchWidth, SwitchHeight)) {
+ val hasInteraction =
+ Interaction.Pressed in interactionState || Interaction.Dragged in interactionState
+ val elevation =
+ if (hasInteraction) {
+ SwitchDefaults.ThumbPressedElevation
+ } else {
+ SwitchDefaults.ThumbDefaultElevation
+ }
+ val trackColor = SwitchDefaults.resolveTrackColor(checked, enabled, checkedColor)
+ val thumbColor = SwitchDefaults.resolveThumbColor(checked, enabled, checkedColor)
+ Canvas(Modifier.gravity(Alignment.Center).preferredSize(SwitchWidth, SwitchHeight)) {
drawTrack(trackColor, TrackWidth.toPx(), TrackStrokeWidth.toPx())
- drawThumb(thumbValue.value, ThumbDiameter.toPx(), thumbColor)
}
+ Surface(
+ shape = CircleShape,
+ color = thumbColor,
+ elevation = elevation,
+ modifier = Modifier
+ .gravity(Alignment.CenterStart)
+ .offsetPx(x = thumbValue)
+ .indication(
+ interactionState = interactionState,
+ indication = RippleIndication(radius = ThumbRippleRadius, bounded = false)
+ )
+ .preferredSize(ThumbDiameter)
+ ) {}
}
private fun DrawScope.drawTrack(trackColor: Color, trackWidth: Float, strokeWidth: Float) {
@@ -119,24 +157,74 @@
)
}
-private fun DrawScope.drawThumb(position: Float, thumbDiameter: Float, thumbColor: Color) {
- val thumbRadius = thumbDiameter / 2
- val x = position + thumbRadius
- drawCircle(thumbColor, thumbRadius, Offset(x, center.y))
-}
+internal val TrackWidth = 34.dp
+internal val TrackStrokeWidth = 14.dp
+internal val ThumbDiameter = 20.dp
-private const val CheckedTrackOpacity = 0.54f
-private const val UncheckedTrackOpacity = 0.38f
+private val ThumbRippleRadius = 24.dp
-private val TrackWidth = 34.dp
-private val TrackStrokeWidth = 14.dp
-
-private val ThumbDiameter = 20.dp
-
-// TODO(malkov): clarify this padding for Switch
private val DefaultSwitchPadding = 2.dp
private val SwitchWidth = TrackWidth
private val SwitchHeight = ThumbDiameter
private val ThumbPathLength = TrackWidth - ThumbDiameter
private val AnimationBuilder = TweenBuilder<Float>().apply { duration = 100 }
+
+internal object SwitchDefaults {
+
+ const val CheckedTrackOpacity = 0.54f
+ const val UncheckedTrackOpacity = 0.38f
+
+ val ThumbDefaultElevation = 1.dp
+ val ThumbPressedElevation = 6.dp
+
+ @Composable
+ private val uncheckedTrackColor
+ get() = MaterialTheme.colors.onSurface
+
+ @Composable
+ private fun makeDisabledCheckedTrackColor(checkedColor: Color) = EmphasisAmbient.current
+ .disabled
+ .applyEmphasis(checkedColor)
+ .compositeOver(MaterialTheme.colors.surface)
+
+ @Composable
+ private val disabledUncheckedTrackColor
+ get() = EmphasisAmbient.current.disabled.applyEmphasis(MaterialTheme.colors.onSurface)
+ .compositeOver(MaterialTheme.colors.surface)
+
+ @Composable
+ private val uncheckedThumbColor
+ get() = MaterialTheme.colors.surface
+
+ @Composable
+ private fun makeDisabledCheckedThumbColor(checkedColor: Color) = EmphasisAmbient.current
+ .disabled
+ .applyEmphasis(checkedColor)
+ .compositeOver(MaterialTheme.colors.surface)
+
+ @Composable
+ private val disabledUncheckedThumbColor
+ get() = EmphasisAmbient.current.disabled.applyEmphasis(MaterialTheme.colors.surface)
+ .compositeOver(MaterialTheme.colors.surface)
+
+ @Composable
+ internal fun resolveTrackColor(checked: Boolean, enabled: Boolean, checkedColor: Color): Color {
+ return if (checked) {
+ val color = if (enabled) checkedColor else makeDisabledCheckedTrackColor(checkedColor)
+ color.copy(alpha = CheckedTrackOpacity)
+ } else {
+ val color = if (enabled) uncheckedTrackColor else disabledUncheckedTrackColor
+ color.copy(alpha = UncheckedTrackOpacity)
+ }
+ }
+
+ @Composable
+ internal fun resolveThumbColor(checked: Boolean, enabled: Boolean, checkedColor: Color): Color {
+ return if (checked) {
+ if (enabled) checkedColor else makeDisabledCheckedThumbColor(checkedColor)
+ } else {
+ if (enabled) uncheckedThumbColor else disabledUncheckedThumbColor
+ }
+ }
+}
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt b/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
index 0b17914..323d931 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/TextField.kt
@@ -82,10 +82,11 @@
import androidx.ui.material.ripple.RippleIndication
import androidx.ui.savedinstancestate.Saver
import androidx.ui.savedinstancestate.rememberSavedInstanceState
+import androidx.ui.text.InternalTextApi
import androidx.ui.text.LastBaseline
import androidx.ui.text.SoftwareKeyboardController
-import androidx.ui.text.TextRange
import androidx.ui.text.TextStyle
+import androidx.ui.text.constrain
import androidx.ui.text.lerp
import androidx.ui.unit.Dp
import androidx.ui.unit.IntSize
@@ -202,11 +203,11 @@
) {
var textFieldValue by state { TextFieldValue() }
if (textFieldValue.text != value) {
- val newSelection = TextRange(
- textFieldValue.selection.start.coerceIn(0, value.length),
- textFieldValue.selection.end.coerceIn(0, value.length)
+ @OptIn(InternalTextApi::class)
+ textFieldValue = TextFieldValue(
+ text = value,
+ selection = textFieldValue.selection.constrain(0, value.length)
)
- textFieldValue = TextFieldValue(text = value, selection = newSelection)
}
TextFieldImpl(
type = TextFieldType.Filled,
@@ -375,13 +376,10 @@
val fullModel = state { TextFieldValue() }
if (fullModel.value.text != value.text || fullModel.value.selection != value.selection) {
- val newSelection = TextRange(
- value.selection.start.coerceIn(0, value.text.length),
- value.selection.end.coerceIn(0, value.text.length)
- )
+ @OptIn(InternalTextApi::class)
fullModel.value = TextFieldValue(
text = value.text,
- selection = newSelection
+ selection = value.selection.constrain(0, value.text.length)
)
}
@@ -500,11 +498,10 @@
) {
var textFieldValue by state { TextFieldValue() }
if (textFieldValue.text != value) {
- val newSelection = TextRange(
- textFieldValue.selection.start.coerceIn(0, value.length),
- textFieldValue.selection.end.coerceIn(0, value.length)
- )
- textFieldValue = TextFieldValue(text = value, selection = newSelection)
+ @OptIn(InternalTextApi::class)
+ textFieldValue = TextFieldValue(
+ text = value,
+ selection = textFieldValue.selection.constrain(0, value.length))
}
TextFieldImpl(
@@ -1510,9 +1507,15 @@
} else {
val effectivePadding = padding - innerPadding - dx - lineWidth / 2
val gap = diff + 2 * innerPadding
- relativeLineTo(-effectiveWidth + effectivePadding + gap, 0f)
- relativeMoveTo(-gap, 0f)
- relativeLineTo(-effectivePadding, 0f)
+ if (layoutDirection == LayoutDirection.Ltr) {
+ relativeLineTo(-effectiveWidth + effectivePadding + gap, 0f)
+ relativeMoveTo(-gap, 0f)
+ relativeLineTo(-effectivePadding, 0f)
+ } else {
+ relativeLineTo(-effectivePadding, 0f)
+ relativeMoveTo(-gap, 0f)
+ relativeLineTo(-effectiveWidth + gap + effectivePadding, 0f)
+ }
}
// top-left corner and left line
diff --git a/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt b/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt
index 7955232..ffab1e3 100644
--- a/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt
+++ b/ui/ui-rxjava2/src/main/java/androidx/ui/rxjava2/RxJava2Adapter.kt
@@ -17,7 +17,6 @@
package androidx.ui.rxjava2
import androidx.compose.Composable
-import androidx.compose.Composer
import androidx.compose.FrameManager
import androidx.compose.State
import androidx.compose.onPreCommit
@@ -197,17 +196,3 @@
}
return state
}
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
- "This property should not be called directly. It is only used by the compiler.",
- replaceWith = ReplaceWith("currentComposer")
-)
-internal val composer: Composer<*>
- get() = error(
- "This property should not be called directly. It is only used by the compiler."
- )
diff --git a/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt b/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
index e7d7037..8dee58a 100644
--- a/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
+++ b/ui/ui-saved-instance-state/src/commonMain/kotlin/androidx/ui/savedinstancestate/UiSavedStateRegistry.kt
@@ -16,7 +16,6 @@
package androidx.ui.savedinstancestate
-import androidx.compose.Composer
import androidx.compose.staticAmbientOf
/**
@@ -121,18 +120,4 @@
}
return map
}
-}
-
-// NOTE(lmr): This API is no longer needed in any way by the compiler, but we still need this API
-// to be here to support versions of Android Studio that are still looking for it. Without it,
-// valid composable code will look broken in the IDE. Remove this after we have left some time to
-// get all versions of Studio upgraded.
-// b/152059242
-@Deprecated(
- "This property should not be called directly. It is only used by the compiler.",
- replaceWith = ReplaceWith("currentComposer")
-)
-internal val composer: Composer<*>
- get() = error(
- "This property should not be called directly. It is only used by the compiler."
- )
+}
\ No newline at end of file
diff --git a/ui/ui-test/api/0.1.0-dev15.txt b/ui/ui-test/api/0.1.0-dev15.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/0.1.0-dev15.txt
+++ b/ui/ui-test/api/0.1.0-dev15.txt
@@ -64,8 +64,11 @@
public final class BoundsAssertionsKt {
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+ method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+ method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+ method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
}
public final class CollectedSizes {
@@ -297,7 +300,7 @@
method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
method public operator androidx.ui.test.SemanticsMatcher not();
method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
- field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+ field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
}
public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/current.txt b/ui/ui-test/api/current.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/current.txt
+++ b/ui/ui-test/api/current.txt
@@ -64,8 +64,11 @@
public final class BoundsAssertionsKt {
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+ method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+ method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+ method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
}
public final class CollectedSizes {
@@ -297,7 +300,7 @@
method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
method public operator androidx.ui.test.SemanticsMatcher not();
method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
- field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+ field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
}
public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-test/api/public_plus_experimental_0.1.0-dev15.txt
@@ -64,8 +64,11 @@
public final class BoundsAssertionsKt {
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+ method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+ method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+ method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
}
public final class CollectedSizes {
@@ -297,7 +300,7 @@
method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
method public operator androidx.ui.test.SemanticsMatcher not();
method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
- field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+ field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
}
public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/public_plus_experimental_current.txt b/ui/ui-test/api/public_plus_experimental_current.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/public_plus_experimental_current.txt
+++ b/ui/ui-test/api/public_plus_experimental_current.txt
@@ -64,8 +64,11 @@
public final class BoundsAssertionsKt {
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+ method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+ method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+ method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
}
public final class CollectedSizes {
@@ -297,7 +300,7 @@
method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
method public operator androidx.ui.test.SemanticsMatcher not();
method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
- field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+ field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
}
public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/restricted_0.1.0-dev15.txt b/ui/ui-test/api/restricted_0.1.0-dev15.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-test/api/restricted_0.1.0-dev15.txt
@@ -64,8 +64,11 @@
public final class BoundsAssertionsKt {
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+ method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+ method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+ method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
}
public final class CollectedSizes {
@@ -297,7 +300,7 @@
method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
method public operator androidx.ui.test.SemanticsMatcher not();
method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
- field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+ field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
}
public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/api/restricted_current.txt b/ui/ui-test/api/restricted_current.txt
index 7959c86..2396104 100644
--- a/ui/ui-test/api/restricted_current.txt
+++ b/ui/ui-test/api/restricted_current.txt
@@ -64,8 +64,11 @@
public final class BoundsAssertionsKt {
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinHeight);
method public static androidx.ui.test.SemanticsNodeInteraction assertHeightIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedHeight);
+ method public static androidx.ui.test.SemanticsNodeInteraction assertPositionInRootIsEqualTo-jINh5Q8(androidx.ui.test.SemanticsNodeInteraction, float expectedLeft, float expectedTop);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsAtLeast-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedMinWidth);
method public static androidx.ui.test.SemanticsNodeInteraction assertWidthIsEqualTo-Gf70O4E(androidx.ui.test.SemanticsNodeInteraction, float expectedWidth);
+ method public static float getAlignmentLinePosition(androidx.ui.test.SemanticsNodeInteraction, androidx.ui.core.AlignmentLine line);
+ method public static androidx.ui.unit.Bounds getBoundsInRoot(androidx.ui.test.SemanticsNodeInteraction);
}
public final class CollectedSizes {
@@ -297,7 +300,7 @@
method public boolean matchesAny(Iterable<androidx.ui.core.semantics.SemanticsNode> nodes);
method public operator androidx.ui.test.SemanticsMatcher not();
method public infix androidx.ui.test.SemanticsMatcher or(androidx.ui.test.SemanticsMatcher other);
- field public static final androidx.ui.test.SemanticsMatcher.Companion! Companion;
+ field public static final androidx.ui.test.SemanticsMatcher.Companion Companion;
}
public static final class SemanticsMatcher.Companion {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
index 7867b1b..4a2ceb7 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
@@ -25,6 +25,7 @@
import androidx.ui.semantics.accessibilityLabel
import androidx.ui.semantics.testTag
import androidx.ui.semantics.text
+import androidx.ui.test.util.expectError
import androidx.ui.text.AnnotatedString
import org.junit.Rule
import org.junit.Test
@@ -112,14 +113,16 @@
findBySubstring("world", ignoreCase = true)
}
- @Test(expected = AssertionError::class)
+ @Test
fun findBySubstring_wrongCase_fails() {
composeTestRule.setContent {
BoundaryNode { text = AnnotatedString("Hello World") }
}
- // Need to assert exists or it won't fail
- findBySubstring("world").assertExists()
+ expectError<AssertionError> {
+ // Need to assert exists or it won't fetch nodes
+ findBySubstring("world").assertExists()
+ }
}
@Composable
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
index aa24a07f..9c4369f 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/SynchronizationMethodsTest.kt
@@ -18,6 +18,7 @@
import androidx.test.filters.MediumTest
import androidx.ui.test.android.AndroidOwnerRegistry
+import androidx.ui.test.util.expectError
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -71,6 +72,39 @@
}
}
+ @Test
+ fun runOnIdleCompose_assert_fails() {
+ withAndroidOwnerRegistry {
+ runOnIdleCompose {
+ expectError<IllegalStateException> {
+ findByTag("dummy").assertExists()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun runOnIdleCompose_waitForIdle_fails() {
+ withAndroidOwnerRegistry {
+ runOnIdleCompose {
+ expectError<IllegalStateException> {
+ waitForIdle()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun runOnIdleCompose_runOnIdleCompose_fails() {
+ withAndroidOwnerRegistry {
+ runOnIdleCompose {
+ expectError<IllegalStateException> {
+ runOnIdleCompose {}
+ }
+ }
+ }
+ }
+
private fun withAndroidOwnerRegistry(block: () -> Unit) {
AndroidOwnerRegistry.setupRegistry()
try {
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt
index 0cbe1b7..64a2ccd 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/assertions/BoundsAssertionsTest.kt
@@ -24,10 +24,12 @@
import androidx.ui.foundation.drawBackground
import androidx.ui.graphics.Color
import androidx.ui.layout.fillMaxSize
+import androidx.ui.layout.padding
import androidx.ui.layout.size
import androidx.ui.layout.wrapContentSize
import androidx.ui.test.assertHeightIsAtLeast
import androidx.ui.test.assertHeightIsEqualTo
+import androidx.ui.test.assertPositionInRootIsEqualTo
import androidx.ui.test.assertWidthIsAtLeast
import androidx.ui.test.assertWidthIsEqualTo
import androidx.ui.test.createComposeRule
@@ -52,13 +54,15 @@
composeTestRule.setContent {
Box(modifier = Modifier
.fillMaxSize()
- .wrapContentSize(Alignment.Center)
+ .wrapContentSize(Alignment.TopStart)
) {
- Box(modifier = Modifier
- .testTag(tag)
- .size(80.dp, 100.dp)
- .drawBackground(Color.Black)
- )
+ Box(modifier = Modifier.padding(start = 50.dp, top = 100.dp)) {
+ Box(modifier = Modifier
+ .testTag(tag)
+ .size(80.dp, 100.dp)
+ .drawBackground(Color.Black)
+ )
+ }
}
}
}
@@ -112,4 +116,27 @@
.assertHeightIsAtLeast(101.dp)
}
}
+
+ @Test
+ fun assertPosition() {
+ composeBox()
+
+ findByTag(tag)
+ .assertPositionInRootIsEqualTo(expectedLeft = 50.dp, expectedTop = 100.dp)
+ }
+
+ @Test
+ fun assertPosition_fail() {
+ composeBox()
+
+ expectError<AssertionError> {
+ findByTag(tag)
+ .assertPositionInRootIsEqualTo(expectedLeft = 51.dp, expectedTop = 101.dp)
+ }
+
+ expectError<AssertionError> {
+ findByTag(tag)
+ .assertPositionInRootIsEqualTo(expectedLeft = 49.dp, expectedTop = 99.dp)
+ }
+ }
}
\ No newline at end of file
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt
index 2accc7a..645898e 100644
--- a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/Expect.kt
@@ -16,39 +16,75 @@
package androidx.ui.test.util
-import com.google.common.truth.Truth.assertWithMessage
import java.io.PrintWriter
import java.io.StringWriter
+import kotlin.text.RegexOption.DOT_MATCHES_ALL
/**
- * Runs the [block] and asserts that an [AssertionError] is thrown if [expectError] is `true`, or
- * that it is not thrown if [expectError] is `false`.
+ * Runs the [block] and asserts that a [AssertionError] is thrown with the [expectedMessage] if
+ * [expectError] is `true`, or that nothing is thrown if [expectError] is `false`. The
+ * [expectedMessage] is a regex with just the option [DOT_MATCHES_ALL] enabled.
*/
-fun expectAssertionError(expectError: Boolean, block: () -> Unit) {
- expectError<AssertionError>(expectError, block)
+fun expectAssertionError(
+ expectError: Boolean,
+ expectedMessage: String = ".*",
+ block: () -> Unit
+) {
+ expectError<AssertionError>(expectError, expectedMessage, block)
}
/**
- * Runs the [block] and asserts that a [T] is thrown if [expectError] is `true`, or that it is
- * not thrown if [expectError] is `false`.
+ * Runs the [block] and asserts that a [T] is thrown with the [expectedMessage] if [expectError]
+ * is `true`, or that nothing is thrown if [expectError] is `false`. The [expectedMessage] is a
+ * regex with just the option [DOT_MATCHES_ALL] enabled.
*/
-inline fun <reified T : Throwable> expectError(expectError: Boolean = true, block: () -> Unit) {
- var thrown = false
- val errorClassName = T::class.java.simpleName
- var errorMessage = "Expected a $errorClassName, got nothing"
+inline fun <reified T : Throwable> expectError(
+ expectError: Boolean = true,
+ expectedMessage: String = ".*",
+ block: () -> Unit
+) {
+ val expectedClassName = T::class.java.simpleName
try {
block()
- } catch (t: Throwable) {
- if (t !is T) {
- throw t
+ } catch (thrown: Throwable) {
+ if (!expectError) {
+ throwExpectError(null, thrown)
+ } else if (thrown !is T) {
+ throwExpectError(expectedClassName, thrown)
+ } else if (!expectedMessage.toRegex(DOT_MATCHES_ALL).matches(thrown.message ?: "")) {
+ throwExpectError(expectedClassName, thrown, expectedMessage)
}
- thrown = true
+ // Thrown error matched what was expected
+ return
+ }
+ if (expectError) {
+ // Nothing was thrown, but we did expect it
+ throwExpectError(expectedClassName)
+ }
+}
+
+@PublishedApi
+internal fun throwExpectError(
+ expectedClassName: String?,
+ thrown: Throwable? = null,
+ expectedMessage: String? = null
+) {
+ val stackTrace = thrown?.let {
StringWriter().use { sw ->
PrintWriter(sw).use { pw ->
- t.printStackTrace(pw)
+ it.printStackTrace(pw)
}
- errorMessage = "Expected no $errorClassName, got:\n==============\n$sw=============="
+ ":\n==============================\n$sw=============================="
}
+ } ?: ""
+
+ fun String.plusMessage(message: String?): String {
+ return if (expectedMessage == null) this else "$this with message \"$message\""
}
- assertWithMessage(errorMessage).that(thrown).isEqualTo(expectError)
+
+ val expected = expectedClassName?.let { "a $it".plusMessage(expectedMessage) } ?: "nothing"
+ val actual = thrown?.run { "a ${javaClass.simpleName}".plusMessage(message) } ?: "nothing"
+ throw AssertionError(
+ "Expected that $expected was thrown, but $actual was thrown$stackTrace"
+ )
}
diff --git a/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ExpectTest.kt b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ExpectTest.kt
new file mode 100644
index 0000000..999b1fb
--- /dev/null
+++ b/ui/ui-test/src/androidTest/java/androidx/ui/test/util/ExpectTest.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.test.util
+
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+
+class ExpectTest {
+
+ class TestException(message: String? = null) : Exception(message)
+
+ @Test
+ fun expectError_gotError() {
+ expectError<TestException> {
+ throw TestException()
+ }
+ }
+
+ @Test
+ fun expectError_gotErrorWithMessage() {
+ expectError<TestException> {
+ throw TestException("message")
+ }
+ }
+
+ @Test
+ fun expectError_gotErrorWithMultilineMessage() {
+ expectError<TestException> {
+ throw TestException("message\nwith 2 lines")
+ }
+ }
+
+ @Test
+ fun expectError_gotNothing() {
+ expectErrorMessage(
+ "Expected that a TestException was thrown, but nothing was thrown"
+ ) {
+ expectError<TestException> {
+ }
+ }
+ }
+
+ @Test
+ fun expectError_gotDifferentError() {
+ expectErrorMessage(
+ "Expected that a TestException was thrown, but a IllegalStateException was thrown:\n=="
+ ) {
+ expectError<TestException> {
+ throw IllegalStateException()
+ }
+ }
+ }
+
+ @Test
+ fun expectNoError_gotNoError() {
+ expectError<TestException>(false) {
+ }
+ }
+
+ @Test
+ fun expectNoError_gotError() {
+ expectErrorMessage(
+ "Expected that nothing was thrown, but a TestException was thrown:\n=="
+ ) {
+ expectError<TestException>(false) {
+ throw TestException()
+ }
+ }
+ }
+
+ @Test
+ fun expectNoError_gotDifferentError() {
+ expectErrorMessage(
+ "Expected that nothing was thrown, but a IllegalStateException was thrown:\n=="
+ ) {
+ expectError<TestException>(false) {
+ throw IllegalStateException()
+ }
+ }
+ }
+
+ @Test
+ fun expectErrorWithMessage_gotErrorWithMessage() {
+ expectError<TestException>(expectedMessage = "message") {
+ throw TestException("message")
+ }
+ }
+
+ @Test
+ fun expectErrorWithMessage_gotErrorWithDifferentMessage() {
+ expectErrorMessage(
+ "Expected that a TestException with message \"message\" was thrown, " +
+ "but a TestException with message \"message x\" was thrown:\n=="
+ ) {
+ expectError<TestException>(expectedMessage = "message") {
+ throw TestException("message x")
+ }
+ }
+ }
+
+ private fun expectErrorMessage(expectedErrorMessage: String, block: () -> Unit) {
+ try {
+ block()
+ } catch (e: AssertionError) {
+ assertWithMessage("expectError threw an AssertionError with the wrong message")
+ .that(e.message)
+ .startsWith(expectedErrorMessage)
+ return
+ }
+ throw AssertionError("Expected an AssertionError, but it wasn't thrown")
+ }
+}
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt b/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt
index 2205c8ce..a16fd1f 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/BoundsAssertions.kt
@@ -16,7 +16,10 @@
package androidx.ui.test
+import androidx.ui.core.AlignmentLine
import androidx.ui.core.AndroidOwner
+import androidx.ui.core.semantics.SemanticsNode
+import androidx.ui.unit.Bounds
import androidx.ui.unit.Density
import androidx.ui.unit.Dp
import androidx.ui.unit.PxBounds
@@ -71,6 +74,64 @@
}
}
+/**
+* Returns the bounds of the layout of this node. The bounds are relative to the root composable.
+*/
+fun SemanticsNodeInteraction.getBoundsInRoot(): Bounds {
+ lateinit var bounds: Bounds
+ withBoundsInRoot {
+ bounds = Bounds(
+ left = it.left.toDp(),
+ top = it.top.toDp(),
+ right = it.right.toDp(),
+ bottom = it.bottom.toDp()
+ )
+ }
+ return bounds
+}
+
+/**
+ * Asserts that the layout of this node has position in the root composable that is equal to the
+ * given position.
+ *
+ * @param expectedLeft The left (x) position to assert.
+ * @param expectedTop The top (y) position to assert.
+ *
+ * @throws AssertionError if comparison fails.
+ */
+fun SemanticsNodeInteraction.assertPositionInRootIsEqualTo(
+ expectedLeft: Dp,
+ expectedTop: Dp
+): SemanticsNodeInteraction {
+ return withBoundsInRoot {
+ areEqualOrThrow("left", it.left, expectedLeft)
+ areEqualOrThrow("top", it.top, expectedTop)
+ }
+}
+
+/**
+ * Returns the position of an [alignment line][AlignmentLine], or [Dp.Unspecified] if the line is
+ * not provided.
+ */
+fun SemanticsNodeInteraction.getAlignmentLinePosition(line: AlignmentLine): Dp {
+ return withDensity {
+ val pos = it.getAlignmentLinePosition(line)
+ if (pos == AlignmentLine.Unspecified) {
+ Dp.Unspecified
+ } else {
+ pos.toDp()
+ }
+ }
+}
+
+private fun <R> SemanticsNodeInteraction.withDensity(
+ operation: Density.(SemanticsNode) -> R
+): R {
+ val node = fetchSemanticsNode("Failed to retrieve density for the node.")
+ val density = (node.componentNode.owner as AndroidOwner).density
+ return operation.invoke(density, node)
+}
+
private fun SemanticsNodeInteraction.withBoundsInRoot(
assertion: Density.(PxBounds) -> Unit
): SemanticsNodeInteraction {
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
index fd004f0..8a9d311 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/Finders.kt
@@ -16,9 +16,6 @@
package androidx.ui.test
-import androidx.ui.core.semantics.SemanticsNode
-import androidx.ui.test.android.SynchronizedTreeCollector
-
/**
* Finds a component identified by the given tag.
*
@@ -115,7 +112,3 @@
fun findAll(matcher: SemanticsMatcher): SemanticsNodeInteractionCollection {
return SemanticsNodeInteractionCollection(SemanticsSelector(matcher))
}
-
-internal fun getAllSemanticsNodes(): List<SemanticsNode> {
- return SynchronizedTreeCollector.collectAllSemanticsNodes()
-}
\ No newline at end of file
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt b/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt
index 1e515ea..f46084a 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/SemanticsNodeInteraction.kt
@@ -17,6 +17,7 @@
package androidx.ui.test
import androidx.ui.core.semantics.SemanticsNode
+import androidx.ui.test.android.SynchronizedTreeCollector.getAllSemanticsNodes
/**
* Represents a semantics node and the path to fetch it from the semantics tree. One can interact
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt
index a7d8174..deba7ae 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/AndroidComposeTestCaseRunner.kt
@@ -30,9 +30,9 @@
import android.widget.ImageView
import androidx.activity.ComponentActivity
import androidx.compose.Composition
-import androidx.compose.CompositionFrameClock
import androidx.compose.FrameManager
import androidx.compose.Recomposer
+import androidx.compose.dispatch.MonotonicFrameClock
import androidx.compose.frames.currentFrame
import androidx.compose.frames.inFrame
import androidx.ui.core.AndroidOwner
@@ -83,7 +83,7 @@
private class AutoFrameClock(
private val singleFrameTimeNanos: Long = 16_000_000
- ) : CompositionFrameClock {
+ ) : MonotonicFrameClock {
private val lastFrameTime = AtomicLong(0L)
override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R =
diff --git a/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt b/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
index 5e95c72..5e90b97 100644
--- a/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
+++ b/ui/ui-test/src/main/java/androidx/ui/test/android/SynchronizedTreeCollector.kt
@@ -43,7 +43,7 @@
* Can crash in case Espresso hits time out. This is not supposed to be handled as it
* surfaces only in incorrect tests.
*/
- internal fun collectAllSemanticsNodes(): List<SemanticsNode> {
+ internal fun getAllSemanticsNodes(): List<SemanticsNode> {
ensureAndroidOwnerRegistryIsSetUp()
// TODO(pavlis): Instead of returning a flatMap, let all consumers handle a tree
@@ -65,6 +65,13 @@
* surfaces only in incorrect tests.
*/
internal fun waitForIdle() {
+ check(!isOnUiThread()) {
+ "Functions that involve synchronization (Assertions, Actions, Synchronization; " +
+ "e.g. assertIsSelected(), doClick(), runOnIdleCompose()) cannot be run " +
+ "from the main thread. Did you nest such a function inside " +
+ "runOnIdleCompose {}, runOnUiThread {} or setContent {}?"
+ }
+
registerComposeWithEspresso()
// First wait for Android mechanisms to settle down
Espresso.onIdle()
diff --git a/ui/ui-text-android/api/0.1.0-dev15.txt b/ui/ui-text-android/api/0.1.0-dev15.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/0.1.0-dev15.txt
+++ b/ui/ui-text-android/api/0.1.0-dev15.txt
@@ -7,6 +7,9 @@
public final class LayoutCompatKt {
}
+ public final class LayoutHelperKt {
+ }
+
public final class LayoutIntrinsicsKt {
}
diff --git a/ui/ui-text-android/api/current.txt b/ui/ui-text-android/api/current.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/current.txt
+++ b/ui/ui-text-android/api/current.txt
@@ -7,6 +7,9 @@
public final class LayoutCompatKt {
}
+ public final class LayoutHelperKt {
+ }
+
public final class LayoutIntrinsicsKt {
}
diff --git a/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-text-android/api/public_plus_experimental_0.1.0-dev15.txt
@@ -7,6 +7,9 @@
public final class LayoutCompatKt {
}
+ public final class LayoutHelperKt {
+ }
+
public final class LayoutIntrinsicsKt {
}
diff --git a/ui/ui-text-android/api/public_plus_experimental_current.txt b/ui/ui-text-android/api/public_plus_experimental_current.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-android/api/public_plus_experimental_current.txt
@@ -7,6 +7,9 @@
public final class LayoutCompatKt {
}
+ public final class LayoutHelperKt {
+ }
+
public final class LayoutIntrinsicsKt {
}
diff --git a/ui/ui-text-android/api/restricted_0.1.0-dev15.txt b/ui/ui-text-android/api/restricted_0.1.0-dev15.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-text-android/api/restricted_0.1.0-dev15.txt
@@ -7,6 +7,9 @@
public final class LayoutCompatKt {
}
+ public final class LayoutHelperKt {
+ }
+
public final class LayoutIntrinsicsKt {
}
diff --git a/ui/ui-text-android/api/restricted_current.txt b/ui/ui-text-android/api/restricted_current.txt
index ddc6f37..9c65639 100644
--- a/ui/ui-text-android/api/restricted_current.txt
+++ b/ui/ui-text-android/api/restricted_current.txt
@@ -7,6 +7,9 @@
public final class LayoutCompatKt {
}
+ public final class LayoutHelperKt {
+ }
+
public final class LayoutIntrinsicsKt {
}
diff --git a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/LayoutHelperParagraphTest.kt b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/LayoutHelperParagraphTest.kt
new file mode 100644
index 0000000..f07fb09
--- /dev/null
+++ b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/LayoutHelperParagraphTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.platform
+
+import android.os.Build
+import android.text.Layout
+import android.text.StaticLayout
+import android.text.TextPaint
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@OptIn(InternalPlatformTextApi::class)
+@RunWith(JUnit4::class)
+class LayoutHelperParagraphTest {
+
+ private val WIDTH = 100
+ private val TEXT_PAINT = TextPaint()
+
+ private fun buildLayoutHelper(text: String): LayoutHelper =
+ if (Build.VERSION.SDK_INT < 23) {
+ @Suppress("DEPRECATION") StaticLayout(text, TEXT_PAINT, WIDTH,
+ Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false)
+ } else {
+ StaticLayout.Builder.obtain(text, 0, text.length, TEXT_PAINT, WIDTH).build()
+ }.let {
+ LayoutHelper(it)
+ }
+
+ @Test
+ fun testParagraphInfo() {
+ val layoutHelper = buildLayoutHelper("a\nb\nc")
+ assertThat(layoutHelper.paragraphCount).isEqualTo(3)
+
+ assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(2)
+
+ assertThat(layoutHelper.getParagraphStart(1)).isEqualTo(2)
+ assertThat(layoutHelper.getParagraphEnd(1)).isEqualTo(4)
+
+ assertThat(layoutHelper.getParagraphStart(2)).isEqualTo(4)
+ assertThat(layoutHelper.getParagraphEnd(2)).isEqualTo(5)
+ }
+
+ @Test
+ fun testParagraphInfo_singleParagraph() {
+ val layoutHelper = buildLayoutHelper("Hello, World.")
+ assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+ assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(layoutHelper.layout.text.length)
+ }
+
+ @Test
+ fun testParagraphInfo_ignoreLastLineFeed() {
+ val layoutHelper = buildLayoutHelper("Hello, World.\n")
+ assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+ assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(layoutHelper.layout.text.length)
+ }
+
+ @Test
+ fun testParagraphInfo_emptyText() {
+ val layoutHelper = buildLayoutHelper("")
+ assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+ assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(0)
+ }
+
+ @Test
+ fun testParagraphInfo_lineFeedOnlyCases() {
+ val layoutHelper = buildLayoutHelper("\n")
+ assertThat(layoutHelper.paragraphCount).isEqualTo(1)
+
+ assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(layoutHelper.layout.text.length)
+ }
+
+ @Test
+ fun testParagraphInfo_lineFeedOnlyCases2() {
+ val layoutHelper = buildLayoutHelper("\n\n")
+ assertThat(layoutHelper.paragraphCount).isEqualTo(2)
+
+ assertThat(layoutHelper.getParagraphStart(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphEnd(0)).isEqualTo(1)
+
+ assertThat(layoutHelper.getParagraphStart(1)).isEqualTo(1)
+ assertThat(layoutHelper.getParagraphEnd(1)).isEqualTo(layoutHelper.layout.text.length)
+ }
+
+ @Test
+ fun testParagraphForOffset() {
+ val layoutHelper = buildLayoutHelper("aa\nbb\ncc")
+ assertThat(layoutHelper.getParagraphForOffset(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphForOffset(1)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphForOffset(2)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphForOffset(3)).isEqualTo(1)
+ assertThat(layoutHelper.getParagraphForOffset(4)).isEqualTo(1)
+ assertThat(layoutHelper.getParagraphForOffset(5)).isEqualTo(1)
+ assertThat(layoutHelper.getParagraphForOffset(6)).isEqualTo(2)
+ assertThat(layoutHelper.getParagraphForOffset(7)).isEqualTo(2)
+ }
+
+ @Test
+ fun testParagraphForOffset_lineFeedOnlyCase() {
+ val layoutHelper = buildLayoutHelper("\n\n")
+ assertThat(layoutHelper.getParagraphForOffset(0)).isEqualTo(0)
+ assertThat(layoutHelper.getParagraphForOffset(1)).isEqualTo(1)
+ }
+
+ @Test
+ fun testParagarphDirection() {
+ val layoutHelper = buildLayoutHelper("aa\nאא\ncc")
+ assertThat(layoutHelper.isRTLParagraph(0)).isFalse()
+ assertThat(layoutHelper.isRTLParagraph(1)).isTrue()
+ assertThat(layoutHelper.isRTLParagraph(2)).isFalse()
+ }
+
+ @Test
+ fun testParagarphDirection_case2() {
+ val layoutHelper = buildLayoutHelper("אא\nbb\nאא")
+ assertThat(layoutHelper.isRTLParagraph(0)).isTrue()
+ assertThat(layoutHelper.isRTLParagraph(1)).isFalse()
+ assertThat(layoutHelper.isRTLParagraph(2)).isTrue()
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt
index af6d8b2..04dc605 100644
--- a/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt
+++ b/ui/ui-text-android/src/androidTest/java/androidx/ui/text/platform/style/PlaceholderSpanTest.kt
@@ -19,11 +19,16 @@
import android.graphics.Paint
import android.text.TextPaint
import androidx.ui.text.platform.InternalPlatformTextApi
+import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
import kotlin.math.abs
@OptIn(InternalPlatformTextApi::class)
+@RunWith(JUnit4::class)
+@SmallTest
class PlaceholderSpanTest {
@Test
fun width_isSp_equalsGiven() {
diff --git a/ui/ui-text-android/src/main/java/androidx/ui/text/platform/LayoutHelper.kt b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/LayoutHelper.kt
new file mode 100644
index 0000000..76cd259
--- /dev/null
+++ b/ui/ui-text-android/src/main/java/androidx/ui/text/platform/LayoutHelper.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.platform
+
+import android.text.Layout
+import androidx.annotation.IntRange
+
+private const val LINE_FEED = '\n'
+
+/**
+ * Provide utilities for Layout class
+ *
+ * @suppress
+ */
+@InternalPlatformTextApi
+class LayoutHelper(val layout: Layout) {
+
+ private val paragraphEnds: List<Int>
+
+ init {
+ var paragraphEnd = 0
+ val lineFeeds = mutableListOf<Int>()
+ do {
+ paragraphEnd = layout.text.indexOf(char = LINE_FEED, startIndex = paragraphEnd)
+ if (paragraphEnd < 0) {
+ // No more LINE_FEED char found. Use the end of the text as the paragraph end.
+ paragraphEnd = layout.text.length
+ } else {
+ // increment since end offset is exclusive.
+ paragraphEnd++
+ }
+ lineFeeds.add(paragraphEnd)
+ } while (paragraphEnd < layout.text.length)
+ paragraphEnds = lineFeeds
+ }
+
+ /**
+ * Retrieve the number of the paragraph in this layout.
+ */
+ val paragraphCount = paragraphEnds.size
+
+ /**
+ * Returns the zero based paragraph number at the offset.
+ *
+ * The paragraphs are divided by line feed character (U+000A) and line feed character is
+ * included in the preceding paragraph, i.e. if the offset points the line feed character,
+ * this function returns preceding paragraph index.
+ *
+ * @param offset a character offset in the text
+ * @return the paragraph number
+ */
+ fun getParagraphForOffset(@IntRange(from = 0) offset: Int): Int =
+ paragraphEnds.binarySearch(offset).let { if (it < 0) - (it + 1) else it + 1 }
+
+ /**
+ * Returns the inclusive paragraph starting offset of the given paragraph index.
+ *
+ * @param paragraphIndex a paragraph index.
+ * @return an inclusive start character offset of the given paragraph.
+ */
+ fun getParagraphStart(@IntRange(from = 0) paragraphIndex: Int) =
+ if (paragraphIndex == 0) 0 else paragraphEnds[paragraphIndex - 1]
+
+ /**
+ * Returns the exclusive paragraph end offset of the given paragraph index.
+ *
+ * @param paragraphIndex a paragraph index.
+ * @return an exclusive end character offset of the given paragraph.
+ */
+ fun getParagraphEnd(@IntRange(from = 0) paragraphIndex: Int) = paragraphEnds[paragraphIndex]
+
+ /**
+ * Returns true if the resolved paragraph direction is RTL, otherwise return false.
+ *
+ * @param paragraphIndex a paragraph index
+ * @return true if the paragraph is RTL, otherwise false
+ */
+ fun isRTLParagraph(@IntRange(from = 0) paragraphIndex: Int): Boolean {
+ val lineNumber = layout.getLineForOffset(getParagraphStart(paragraphIndex))
+ return layout.getParagraphDirection(lineNumber) == Layout.DIR_RIGHT_TO_LEFT
+ }
+}
\ No newline at end of file
diff --git a/ui/ui-text-core/api/0.1.0-dev14.txt b/ui/ui-text-core/api/0.1.0-dev14.txt
index b84e856..b3f847a 100644
--- a/ui/ui-text-core/api/0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/0.1.0-dev14.txt
@@ -892,14 +892,21 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
}
+ @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
+ }
+
public final class TypefaceAdapterKt {
method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
}
diff --git a/ui/ui-text-core/api/0.1.0-dev15.txt b/ui/ui-text-core/api/0.1.0-dev15.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/0.1.0-dev15.txt
+++ b/ui/ui-text-core/api/0.1.0-dev15.txt
@@ -74,6 +74,8 @@
}
public enum ImeAction {
+ method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.ImeAction[] values();
enum_constant public static final androidx.ui.input.ImeAction Done;
enum_constant public static final androidx.ui.input.ImeAction Go;
enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
}
public enum KeyboardType {
+ method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.KeyboardType[] values();
enum_constant public static final androidx.ui.input.KeyboardType Ascii;
enum_constant public static final androidx.ui.input.KeyboardType Email;
enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
public interface OffsetMap {
method public int originalToTransformed(int offset);
method public int transformedToOriginal(int offset);
- field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+ field public static final androidx.ui.input.OffsetMap.Companion Companion;
}
public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
method public androidx.ui.text.TextRange? getComposition();
method public androidx.ui.text.TextRange getSelection();
method public String getText();
- field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+ field public static final androidx.ui.input.TextFieldValue.Companion Companion;
}
public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
@androidx.compose.Immutable public interface VisualTransformation {
method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
- field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+ field public static final androidx.ui.input.VisualTransformation.Companion Companion;
}
public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
property public final String language;
property public final String region;
property public final String script;
- field public static final androidx.ui.intl.Locale.Companion! Companion;
+ field public static final androidx.ui.intl.Locale.Companion Companion;
}
public static final class Locale.Companion {
@@ -265,7 +269,7 @@
method public boolean isEmpty();
method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
property public int size;
- field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+ field public static final androidx.ui.intl.LocaleList.Companion Companion;
}
public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
}
public enum PlaceholderVerticalAlign {
+ method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
public final class TextPainter {
method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
- field public static final androidx.ui.text.TextPainter! INSTANCE;
+ field public static final androidx.ui.text.TextPainter INSTANCE;
}
@androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
method public int getLength();
method public int getMax();
method public int getMin();
+ method public boolean getReversed();
method public int getStart();
method public boolean intersects(androidx.ui.text.TextRange other);
property public final boolean collapsed;
property public final int length;
property public final int max;
property public final int min;
- field public static final androidx.ui.text.TextRange.Companion! Companion;
+ property public final boolean reversed;
+ field public static final androidx.ui.text.TextRange.Companion Companion;
}
public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
- field public static final androidx.ui.text.TextStyle.Companion! Companion;
+ field public static final androidx.ui.text.TextStyle.Companion Companion;
}
public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
@androidx.compose.Immutable public abstract sealed class FontFamily {
method public final boolean getCanLoadSynchronously();
- field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+ field public static final androidx.ui.text.font.FontFamily.Companion Companion;
}
public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
}
public enum FontStyle {
+ method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontStyle[] values();
enum_constant public static final androidx.ui.text.font.FontStyle Italic;
enum_constant public static final androidx.ui.text.font.FontStyle Normal;
}
public enum FontSynthesis {
+ method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontSynthesis[] values();
enum_constant public static final androidx.ui.text.font.FontSynthesis All;
enum_constant public static final androidx.ui.text.font.FontSynthesis None;
enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
method public int component1();
method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
method public int getWeight();
- field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+ field public static final androidx.ui.text.font.FontWeight.Companion Companion;
}
public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
method public float getMultiplier();
method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
method @androidx.compose.Immutable public static inline String! toString-impl(float p);
- field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+ field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
}
public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
}
public enum TextAlign {
+ method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextAlign[] values();
enum_constant public static final androidx.ui.text.style.TextAlign Center;
enum_constant public static final androidx.ui.text.style.TextAlign End;
enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
method public boolean contains(androidx.ui.text.style.TextDecoration other);
method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
method public int getMask();
- field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+ field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
}
public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
}
public enum TextDirection {
+ method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirection[] values();
enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
}
public enum TextDirectionAlgorithm {
+ method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
method public float getScaleX();
method public float getSkewX();
- field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+ field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
}
public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
method public long getFirstLine();
method public long getRestLine();
- field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+ field public static final androidx.ui.text.style.TextIndent.Companion Companion;
}
public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
}
public enum TextOverflow {
+ method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextOverflow[] values();
enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
}
diff --git a/ui/ui-text-core/api/current.txt b/ui/ui-text-core/api/current.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/current.txt
+++ b/ui/ui-text-core/api/current.txt
@@ -74,6 +74,8 @@
}
public enum ImeAction {
+ method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.ImeAction[] values();
enum_constant public static final androidx.ui.input.ImeAction Done;
enum_constant public static final androidx.ui.input.ImeAction Go;
enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
}
public enum KeyboardType {
+ method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.KeyboardType[] values();
enum_constant public static final androidx.ui.input.KeyboardType Ascii;
enum_constant public static final androidx.ui.input.KeyboardType Email;
enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
public interface OffsetMap {
method public int originalToTransformed(int offset);
method public int transformedToOriginal(int offset);
- field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+ field public static final androidx.ui.input.OffsetMap.Companion Companion;
}
public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
method public androidx.ui.text.TextRange? getComposition();
method public androidx.ui.text.TextRange getSelection();
method public String getText();
- field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+ field public static final androidx.ui.input.TextFieldValue.Companion Companion;
}
public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
@androidx.compose.Immutable public interface VisualTransformation {
method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
- field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+ field public static final androidx.ui.input.VisualTransformation.Companion Companion;
}
public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
property public final String language;
property public final String region;
property public final String script;
- field public static final androidx.ui.intl.Locale.Companion! Companion;
+ field public static final androidx.ui.intl.Locale.Companion Companion;
}
public static final class Locale.Companion {
@@ -265,7 +269,7 @@
method public boolean isEmpty();
method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
property public int size;
- field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+ field public static final androidx.ui.intl.LocaleList.Companion Companion;
}
public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
}
public enum PlaceholderVerticalAlign {
+ method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
public final class TextPainter {
method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
- field public static final androidx.ui.text.TextPainter! INSTANCE;
+ field public static final androidx.ui.text.TextPainter INSTANCE;
}
@androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
method public int getLength();
method public int getMax();
method public int getMin();
+ method public boolean getReversed();
method public int getStart();
method public boolean intersects(androidx.ui.text.TextRange other);
property public final boolean collapsed;
property public final int length;
property public final int max;
property public final int min;
- field public static final androidx.ui.text.TextRange.Companion! Companion;
+ property public final boolean reversed;
+ field public static final androidx.ui.text.TextRange.Companion Companion;
}
public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
- field public static final androidx.ui.text.TextStyle.Companion! Companion;
+ field public static final androidx.ui.text.TextStyle.Companion Companion;
}
public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
@androidx.compose.Immutable public abstract sealed class FontFamily {
method public final boolean getCanLoadSynchronously();
- field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+ field public static final androidx.ui.text.font.FontFamily.Companion Companion;
}
public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
}
public enum FontStyle {
+ method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontStyle[] values();
enum_constant public static final androidx.ui.text.font.FontStyle Italic;
enum_constant public static final androidx.ui.text.font.FontStyle Normal;
}
public enum FontSynthesis {
+ method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontSynthesis[] values();
enum_constant public static final androidx.ui.text.font.FontSynthesis All;
enum_constant public static final androidx.ui.text.font.FontSynthesis None;
enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
method public int component1();
method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
method public int getWeight();
- field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+ field public static final androidx.ui.text.font.FontWeight.Companion Companion;
}
public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
method public float getMultiplier();
method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
method @androidx.compose.Immutable public static inline String! toString-impl(float p);
- field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+ field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
}
public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
}
public enum TextAlign {
+ method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextAlign[] values();
enum_constant public static final androidx.ui.text.style.TextAlign Center;
enum_constant public static final androidx.ui.text.style.TextAlign End;
enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
method public boolean contains(androidx.ui.text.style.TextDecoration other);
method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
method public int getMask();
- field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+ field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
}
public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
}
public enum TextDirection {
+ method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirection[] values();
enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
}
public enum TextDirectionAlgorithm {
+ method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
method public float getScaleX();
method public float getSkewX();
- field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+ field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
}
public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
method public long getFirstLine();
method public long getRestLine();
- field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+ field public static final androidx.ui.text.style.TextIndent.Companion Companion;
}
public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
}
public enum TextOverflow {
+ method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextOverflow[] values();
enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
}
diff --git a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt
index b84e856..b3f847a 100644
--- a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev14.txt
@@ -892,14 +892,21 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
}
+ @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
+ }
+
public final class TypefaceAdapterKt {
method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
}
diff --git a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_0.1.0-dev15.txt
@@ -74,6 +74,8 @@
}
public enum ImeAction {
+ method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.ImeAction[] values();
enum_constant public static final androidx.ui.input.ImeAction Done;
enum_constant public static final androidx.ui.input.ImeAction Go;
enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
}
public enum KeyboardType {
+ method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.KeyboardType[] values();
enum_constant public static final androidx.ui.input.KeyboardType Ascii;
enum_constant public static final androidx.ui.input.KeyboardType Email;
enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
public interface OffsetMap {
method public int originalToTransformed(int offset);
method public int transformedToOriginal(int offset);
- field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+ field public static final androidx.ui.input.OffsetMap.Companion Companion;
}
public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
method public androidx.ui.text.TextRange? getComposition();
method public androidx.ui.text.TextRange getSelection();
method public String getText();
- field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+ field public static final androidx.ui.input.TextFieldValue.Companion Companion;
}
public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
@androidx.compose.Immutable public interface VisualTransformation {
method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
- field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+ field public static final androidx.ui.input.VisualTransformation.Companion Companion;
}
public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
property public final String language;
property public final String region;
property public final String script;
- field public static final androidx.ui.intl.Locale.Companion! Companion;
+ field public static final androidx.ui.intl.Locale.Companion Companion;
}
public static final class Locale.Companion {
@@ -265,7 +269,7 @@
method public boolean isEmpty();
method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
property public int size;
- field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+ field public static final androidx.ui.intl.LocaleList.Companion Companion;
}
public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
}
public enum PlaceholderVerticalAlign {
+ method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
public final class TextPainter {
method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
- field public static final androidx.ui.text.TextPainter! INSTANCE;
+ field public static final androidx.ui.text.TextPainter INSTANCE;
}
@androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
method public int getLength();
method public int getMax();
method public int getMin();
+ method public boolean getReversed();
method public int getStart();
method public boolean intersects(androidx.ui.text.TextRange other);
property public final boolean collapsed;
property public final int length;
property public final int max;
property public final int min;
- field public static final androidx.ui.text.TextRange.Companion! Companion;
+ property public final boolean reversed;
+ field public static final androidx.ui.text.TextRange.Companion Companion;
}
public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
- field public static final androidx.ui.text.TextStyle.Companion! Companion;
+ field public static final androidx.ui.text.TextStyle.Companion Companion;
}
public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
@androidx.compose.Immutable public abstract sealed class FontFamily {
method public final boolean getCanLoadSynchronously();
- field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+ field public static final androidx.ui.text.font.FontFamily.Companion Companion;
}
public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
}
public enum FontStyle {
+ method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontStyle[] values();
enum_constant public static final androidx.ui.text.font.FontStyle Italic;
enum_constant public static final androidx.ui.text.font.FontStyle Normal;
}
public enum FontSynthesis {
+ method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontSynthesis[] values();
enum_constant public static final androidx.ui.text.font.FontSynthesis All;
enum_constant public static final androidx.ui.text.font.FontSynthesis None;
enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
method public int component1();
method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
method public int getWeight();
- field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+ field public static final androidx.ui.text.font.FontWeight.Companion Companion;
}
public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
method public float getMultiplier();
method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
method @androidx.compose.Immutable public static inline String! toString-impl(float p);
- field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+ field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
}
public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
}
public enum TextAlign {
+ method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextAlign[] values();
enum_constant public static final androidx.ui.text.style.TextAlign Center;
enum_constant public static final androidx.ui.text.style.TextAlign End;
enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
method public boolean contains(androidx.ui.text.style.TextDecoration other);
method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
method public int getMask();
- field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+ field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
}
public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
}
public enum TextDirection {
+ method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirection[] values();
enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
}
public enum TextDirectionAlgorithm {
+ method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
method public float getScaleX();
method public float getSkewX();
- field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+ field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
}
public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
method public long getFirstLine();
method public long getRestLine();
- field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+ field public static final androidx.ui.text.style.TextIndent.Companion Companion;
}
public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
}
public enum TextOverflow {
+ method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextOverflow[] values();
enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
}
diff --git a/ui/ui-text-core/api/public_plus_experimental_current.txt b/ui/ui-text-core/api/public_plus_experimental_current.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-text-core/api/public_plus_experimental_current.txt
@@ -74,6 +74,8 @@
}
public enum ImeAction {
+ method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.ImeAction[] values();
enum_constant public static final androidx.ui.input.ImeAction Done;
enum_constant public static final androidx.ui.input.ImeAction Go;
enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
}
public enum KeyboardType {
+ method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.KeyboardType[] values();
enum_constant public static final androidx.ui.input.KeyboardType Ascii;
enum_constant public static final androidx.ui.input.KeyboardType Email;
enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
public interface OffsetMap {
method public int originalToTransformed(int offset);
method public int transformedToOriginal(int offset);
- field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+ field public static final androidx.ui.input.OffsetMap.Companion Companion;
}
public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
method public androidx.ui.text.TextRange? getComposition();
method public androidx.ui.text.TextRange getSelection();
method public String getText();
- field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+ field public static final androidx.ui.input.TextFieldValue.Companion Companion;
}
public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
@androidx.compose.Immutable public interface VisualTransformation {
method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
- field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+ field public static final androidx.ui.input.VisualTransformation.Companion Companion;
}
public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
property public final String language;
property public final String region;
property public final String script;
- field public static final androidx.ui.intl.Locale.Companion! Companion;
+ field public static final androidx.ui.intl.Locale.Companion Companion;
}
public static final class Locale.Companion {
@@ -265,7 +269,7 @@
method public boolean isEmpty();
method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
property public int size;
- field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+ field public static final androidx.ui.intl.LocaleList.Companion Companion;
}
public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
}
public enum PlaceholderVerticalAlign {
+ method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
public final class TextPainter {
method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
- field public static final androidx.ui.text.TextPainter! INSTANCE;
+ field public static final androidx.ui.text.TextPainter INSTANCE;
}
@androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
method public int getLength();
method public int getMax();
method public int getMin();
+ method public boolean getReversed();
method public int getStart();
method public boolean intersects(androidx.ui.text.TextRange other);
property public final boolean collapsed;
property public final int length;
property public final int max;
property public final int min;
- field public static final androidx.ui.text.TextRange.Companion! Companion;
+ property public final boolean reversed;
+ field public static final androidx.ui.text.TextRange.Companion Companion;
}
public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
- field public static final androidx.ui.text.TextStyle.Companion! Companion;
+ field public static final androidx.ui.text.TextStyle.Companion Companion;
}
public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
@androidx.compose.Immutable public abstract sealed class FontFamily {
method public final boolean getCanLoadSynchronously();
- field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+ field public static final androidx.ui.text.font.FontFamily.Companion Companion;
}
public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
}
public enum FontStyle {
+ method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontStyle[] values();
enum_constant public static final androidx.ui.text.font.FontStyle Italic;
enum_constant public static final androidx.ui.text.font.FontStyle Normal;
}
public enum FontSynthesis {
+ method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontSynthesis[] values();
enum_constant public static final androidx.ui.text.font.FontSynthesis All;
enum_constant public static final androidx.ui.text.font.FontSynthesis None;
enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
method public int component1();
method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
method public int getWeight();
- field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+ field public static final androidx.ui.text.font.FontWeight.Companion Companion;
}
public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
method public float getMultiplier();
method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
method @androidx.compose.Immutable public static inline String! toString-impl(float p);
- field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+ field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
}
public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
}
public enum TextAlign {
+ method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextAlign[] values();
enum_constant public static final androidx.ui.text.style.TextAlign Center;
enum_constant public static final androidx.ui.text.style.TextAlign End;
enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
method public boolean contains(androidx.ui.text.style.TextDecoration other);
method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
method public int getMask();
- field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+ field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
}
public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
}
public enum TextDirection {
+ method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirection[] values();
enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
}
public enum TextDirectionAlgorithm {
+ method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
method public float getScaleX();
method public float getSkewX();
- field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+ field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
}
public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
method public long getFirstLine();
method public long getRestLine();
- field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+ field public static final androidx.ui.text.style.TextIndent.Companion Companion;
}
public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
}
public enum TextOverflow {
+ method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextOverflow[] values();
enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
}
diff --git a/ui/ui-text-core/api/restricted_0.1.0-dev14.txt b/ui/ui-text-core/api/restricted_0.1.0-dev14.txt
index b84e856..b3f847a 100644
--- a/ui/ui-text-core/api/restricted_0.1.0-dev14.txt
+++ b/ui/ui-text-core/api/restricted_0.1.0-dev14.txt
@@ -892,14 +892,21 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
}
+ @kotlin.RequiresOptIn(message="This API is internal to library.") @kotlin.annotation.Target(allowedTargets={AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY}) public @interface InternalTextApi {
+ }
+
public final class TypefaceAdapterKt {
method public static androidx.ui.text.Typeface typefaceFromFontFamily(android.content.Context context, androidx.ui.text.font.FontFamily fontFamily, java.util.List<? extends kotlin.Pair<androidx.ui.text.font.FontWeight,? extends androidx.ui.text.font.FontStyle>>? necessaryStyles = null);
}
diff --git a/ui/ui-text-core/api/restricted_0.1.0-dev15.txt b/ui/ui-text-core/api/restricted_0.1.0-dev15.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-text-core/api/restricted_0.1.0-dev15.txt
@@ -74,6 +74,8 @@
}
public enum ImeAction {
+ method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.ImeAction[] values();
enum_constant public static final androidx.ui.input.ImeAction Done;
enum_constant public static final androidx.ui.input.ImeAction Go;
enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
}
public enum KeyboardType {
+ method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.KeyboardType[] values();
enum_constant public static final androidx.ui.input.KeyboardType Ascii;
enum_constant public static final androidx.ui.input.KeyboardType Email;
enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
public interface OffsetMap {
method public int originalToTransformed(int offset);
method public int transformedToOriginal(int offset);
- field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+ field public static final androidx.ui.input.OffsetMap.Companion Companion;
}
public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
method public androidx.ui.text.TextRange? getComposition();
method public androidx.ui.text.TextRange getSelection();
method public String getText();
- field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+ field public static final androidx.ui.input.TextFieldValue.Companion Companion;
}
public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
@androidx.compose.Immutable public interface VisualTransformation {
method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
- field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+ field public static final androidx.ui.input.VisualTransformation.Companion Companion;
}
public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
property public final String language;
property public final String region;
property public final String script;
- field public static final androidx.ui.intl.Locale.Companion! Companion;
+ field public static final androidx.ui.intl.Locale.Companion Companion;
}
public static final class Locale.Companion {
@@ -265,7 +269,7 @@
method public boolean isEmpty();
method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
property public int size;
- field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+ field public static final androidx.ui.intl.LocaleList.Companion Companion;
}
public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
}
public enum PlaceholderVerticalAlign {
+ method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
public final class TextPainter {
method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
- field public static final androidx.ui.text.TextPainter! INSTANCE;
+ field public static final androidx.ui.text.TextPainter INSTANCE;
}
@androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
method public int getLength();
method public int getMax();
method public int getMin();
+ method public boolean getReversed();
method public int getStart();
method public boolean intersects(androidx.ui.text.TextRange other);
property public final boolean collapsed;
property public final int length;
property public final int max;
property public final int min;
- field public static final androidx.ui.text.TextRange.Companion! Companion;
+ property public final boolean reversed;
+ field public static final androidx.ui.text.TextRange.Companion Companion;
}
public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
- field public static final androidx.ui.text.TextStyle.Companion! Companion;
+ field public static final androidx.ui.text.TextStyle.Companion Companion;
}
public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
@androidx.compose.Immutable public abstract sealed class FontFamily {
method public final boolean getCanLoadSynchronously();
- field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+ field public static final androidx.ui.text.font.FontFamily.Companion Companion;
}
public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
}
public enum FontStyle {
+ method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontStyle[] values();
enum_constant public static final androidx.ui.text.font.FontStyle Italic;
enum_constant public static final androidx.ui.text.font.FontStyle Normal;
}
public enum FontSynthesis {
+ method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontSynthesis[] values();
enum_constant public static final androidx.ui.text.font.FontSynthesis All;
enum_constant public static final androidx.ui.text.font.FontSynthesis None;
enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
method public int component1();
method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
method public int getWeight();
- field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+ field public static final androidx.ui.text.font.FontWeight.Companion Companion;
}
public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
method public float getMultiplier();
method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
method @androidx.compose.Immutable public static inline String! toString-impl(float p);
- field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+ field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
}
public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
}
public enum TextAlign {
+ method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextAlign[] values();
enum_constant public static final androidx.ui.text.style.TextAlign Center;
enum_constant public static final androidx.ui.text.style.TextAlign End;
enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
method public boolean contains(androidx.ui.text.style.TextDecoration other);
method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
method public int getMask();
- field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+ field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
}
public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
}
public enum TextDirection {
+ method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirection[] values();
enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
}
public enum TextDirectionAlgorithm {
+ method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
method public float getScaleX();
method public float getSkewX();
- field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+ field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
}
public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
method public long getFirstLine();
method public long getRestLine();
- field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+ field public static final androidx.ui.text.style.TextIndent.Companion Companion;
}
public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
}
public enum TextOverflow {
+ method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextOverflow[] values();
enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
}
diff --git a/ui/ui-text-core/api/restricted_current.txt b/ui/ui-text-core/api/restricted_current.txt
index b84e856..bc4564e 100644
--- a/ui/ui-text-core/api/restricted_current.txt
+++ b/ui/ui-text-core/api/restricted_current.txt
@@ -74,6 +74,8 @@
}
public enum ImeAction {
+ method public static androidx.ui.input.ImeAction valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.ImeAction[] values();
enum_constant public static final androidx.ui.input.ImeAction Done;
enum_constant public static final androidx.ui.input.ImeAction Go;
enum_constant public static final androidx.ui.input.ImeAction Next;
@@ -90,6 +92,8 @@
}
public enum KeyboardType {
+ method public static androidx.ui.input.KeyboardType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.input.KeyboardType[] values();
enum_constant public static final androidx.ui.input.KeyboardType Ascii;
enum_constant public static final androidx.ui.input.KeyboardType Email;
enum_constant public static final androidx.ui.input.KeyboardType Number;
@@ -111,7 +115,7 @@
public interface OffsetMap {
method public int originalToTransformed(int offset);
method public int transformedToOriginal(int offset);
- field public static final androidx.ui.input.OffsetMap.Companion! Companion;
+ field public static final androidx.ui.input.OffsetMap.Companion Companion;
}
public static final class OffsetMap.Companion {
@@ -177,7 +181,7 @@
method public androidx.ui.text.TextRange? getComposition();
method public androidx.ui.text.TextRange getSelection();
method public String getText();
- field public static final androidx.ui.input.TextFieldValue.Companion! Companion;
+ field public static final androidx.ui.input.TextFieldValue.Companion Companion;
}
public static final class TextFieldValue.Companion {
@@ -219,7 +223,7 @@
@androidx.compose.Immutable public interface VisualTransformation {
method public androidx.ui.input.TransformedText filter(androidx.ui.text.AnnotatedString text);
- field public static final androidx.ui.input.VisualTransformation.Companion! Companion;
+ field public static final androidx.ui.input.VisualTransformation.Companion Companion;
}
public static final class VisualTransformation.Companion {
@@ -243,7 +247,7 @@
property public final String language;
property public final String region;
property public final String script;
- field public static final androidx.ui.intl.Locale.Companion! Companion;
+ field public static final androidx.ui.intl.Locale.Companion Companion;
}
public static final class Locale.Companion {
@@ -265,7 +269,7 @@
method public boolean isEmpty();
method public java.util.Iterator<androidx.ui.intl.Locale> iterator();
property public int size;
- field public static final androidx.ui.intl.LocaleList.Companion! Companion;
+ field public static final androidx.ui.intl.LocaleList.Companion Companion;
}
public static final class LocaleList.Companion {
@@ -504,6 +508,8 @@
}
public enum PlaceholderVerticalAlign {
+ method public static androidx.ui.text.PlaceholderVerticalAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.PlaceholderVerticalAlign[] values();
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign AboveBaseline;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Bottom;
enum_constant public static final androidx.ui.text.PlaceholderVerticalAlign Center;
@@ -632,7 +638,7 @@
public final class TextPainter {
method public void paint(androidx.ui.graphics.Canvas canvas, androidx.ui.text.TextLayoutResult textLayoutResult);
- field public static final androidx.ui.text.TextPainter! INSTANCE;
+ field public static final androidx.ui.text.TextPainter INSTANCE;
}
@androidx.compose.Immutable public final class TextRange {
@@ -647,13 +653,15 @@
method public int getLength();
method public int getMax();
method public int getMin();
+ method public boolean getReversed();
method public int getStart();
method public boolean intersects(androidx.ui.text.TextRange other);
property public final boolean collapsed;
property public final int length;
property public final int max;
property public final int min;
- field public static final androidx.ui.text.TextRange.Companion! Companion;
+ property public final boolean reversed;
+ field public static final androidx.ui.text.TextRange.Companion Companion;
}
public static final class TextRange.Companion {
@@ -712,7 +720,7 @@
method @androidx.compose.Stable public operator androidx.ui.text.TextStyle plus(androidx.ui.text.SpanStyle other);
method @androidx.compose.Stable public androidx.ui.text.ParagraphStyle toParagraphStyle();
method @androidx.compose.Stable public androidx.ui.text.SpanStyle toSpanStyle();
- field public static final androidx.ui.text.TextStyle.Companion! Companion;
+ field public static final androidx.ui.text.TextStyle.Companion Companion;
}
public static final class TextStyle.Companion {
@@ -750,7 +758,7 @@
@androidx.compose.Immutable public abstract sealed class FontFamily {
method public final boolean getCanLoadSynchronously();
- field public static final androidx.ui.text.font.FontFamily.Companion! Companion;
+ field public static final androidx.ui.text.font.FontFamily.Companion Companion;
}
public static final class FontFamily.Companion {
@@ -796,11 +804,15 @@
}
public enum FontStyle {
+ method public static androidx.ui.text.font.FontStyle valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontStyle[] values();
enum_constant public static final androidx.ui.text.font.FontStyle Italic;
enum_constant public static final androidx.ui.text.font.FontStyle Normal;
}
public enum FontSynthesis {
+ method public static androidx.ui.text.font.FontSynthesis valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.font.FontSynthesis[] values();
enum_constant public static final androidx.ui.text.font.FontSynthesis All;
enum_constant public static final androidx.ui.text.font.FontSynthesis None;
enum_constant public static final androidx.ui.text.font.FontSynthesis Style;
@@ -813,7 +825,7 @@
method public int component1();
method @androidx.compose.Immutable public androidx.ui.text.font.FontWeight copy(int weight);
method public int getWeight();
- field public static final androidx.ui.text.font.FontWeight.Companion! Companion;
+ field public static final androidx.ui.text.font.FontWeight.Companion Companion;
}
public static final class FontWeight.Companion {
@@ -892,9 +904,13 @@
}
public final class AndroidParagraphIntrinsicsKt {
+ method @Deprecated public static kotlin.jvm.functions.Function6<java.lang.String,androidx.ui.text.TextStyle,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,androidx.ui.unit.Density,androidx.ui.text.font.Font.ResourceLoader,androidx.ui.text.ParagraphIntrinsics> getParagraphIntrinsicsActualFactory();
+ method @Deprecated public static void setParagraphIntrinsicsActualFactory(kotlin.jvm.functions.Function6<? super java.lang.String,? super androidx.ui.text.TextStyle,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.SpanStyle>>,? super java.util.List<androidx.ui.text.AnnotatedString.Range<androidx.ui.text.Placeholder>>,? super androidx.ui.unit.Density,? super androidx.ui.text.font.Font.ResourceLoader,? extends androidx.ui.text.ParagraphIntrinsics> p);
}
public final class AndroidParagraphKt {
+ method @Deprecated public static kotlin.jvm.functions.Function4<androidx.ui.text.ParagraphIntrinsics,java.lang.Integer,java.lang.Boolean,androidx.ui.text.ParagraphConstraints,androidx.ui.text.Paragraph> getParagraphActualFactory();
+ method @Deprecated public static void setParagraphActualFactory(kotlin.jvm.functions.Function4<? super androidx.ui.text.ParagraphIntrinsics,? super java.lang.Integer,? super java.lang.Boolean,? super androidx.ui.text.ParagraphConstraints,? extends androidx.ui.text.Paragraph> p);
}
public final class AndroidStringDelegateKt {
@@ -916,7 +932,7 @@
method public float getMultiplier();
method @androidx.compose.Immutable public static inline int hashCode-impl(float p);
method @androidx.compose.Immutable public static inline String! toString-impl(float p);
- field public static final androidx.ui.text.style.BaselineShift.Companion! Companion;
+ field public static final androidx.ui.text.style.BaselineShift.Companion Companion;
}
public static final class BaselineShift.Companion {
@@ -933,6 +949,8 @@
}
public enum TextAlign {
+ method public static androidx.ui.text.style.TextAlign valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextAlign[] values();
enum_constant public static final androidx.ui.text.style.TextAlign Center;
enum_constant public static final androidx.ui.text.style.TextAlign End;
enum_constant public static final androidx.ui.text.style.TextAlign Justify;
@@ -946,7 +964,7 @@
method public boolean contains(androidx.ui.text.style.TextDecoration other);
method @androidx.compose.Immutable public androidx.ui.text.style.TextDecoration copy(int mask);
method public int getMask();
- field public static final androidx.ui.text.style.TextDecoration.Companion! Companion;
+ field public static final androidx.ui.text.style.TextDecoration.Companion Companion;
}
public static final class TextDecoration.Companion {
@@ -960,11 +978,15 @@
}
public enum TextDirection {
+ method public static androidx.ui.text.style.TextDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirection[] values();
enum_constant public static final androidx.ui.text.style.TextDirection Ltr;
enum_constant public static final androidx.ui.text.style.TextDirection Rtl;
}
public enum TextDirectionAlgorithm {
+ method public static androidx.ui.text.style.TextDirectionAlgorithm valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextDirectionAlgorithm[] values();
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrLtr;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ContentOrRtl;
enum_constant public static final androidx.ui.text.style.TextDirectionAlgorithm ForceLtr;
@@ -979,7 +1001,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextGeometricTransform copy(float scaleX, float skewX);
method public float getScaleX();
method public float getSkewX();
- field public static final androidx.ui.text.style.TextGeometricTransform.Companion! Companion;
+ field public static final androidx.ui.text.style.TextGeometricTransform.Companion Companion;
}
public static final class TextGeometricTransform.Companion {
@@ -995,7 +1017,7 @@
method @androidx.compose.Immutable public androidx.ui.text.style.TextIndent copy-gL_aCS0(long firstLine, long restLine);
method public long getFirstLine();
method public long getRestLine();
- field public static final androidx.ui.text.style.TextIndent.Companion! Companion;
+ field public static final androidx.ui.text.style.TextIndent.Companion Companion;
}
public static final class TextIndent.Companion {
@@ -1008,6 +1030,8 @@
}
public enum TextOverflow {
+ method public static androidx.ui.text.style.TextOverflow valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.text.style.TextOverflow[] values();
enum_constant public static final androidx.ui.text.style.TextOverflow Clip;
enum_constant public static final androidx.ui.text.style.TextOverflow Ellipsis;
}
diff --git a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
index 6c9ac37..b79162c 100644
--- a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraph.kt
@@ -338,6 +338,26 @@
else -> DEFAULT_ALIGNMENT
}
+// TODO(b/159152328): temporary workaround for ui-desktop. remove when full support of MPP will be in-place
+@Deprecated(
+ "Temporary workaround. Supposed to be used only in ui-desktop before MPP",
+ level = DeprecationLevel.ERROR
+)
+@InternalPlatformTextApi
+var paragraphActualFactory: ((
+ paragraphIntrinsics: ParagraphIntrinsics,
+ maxLines: Int,
+ ellipsis: Boolean,
+ constraints: ParagraphConstraints
+) -> Paragraph) = { paragraphIntrinsics, maxLines, ellipsis, constraints ->
+ AndroidParagraph(
+ paragraphIntrinsics as AndroidParagraphIntrinsics,
+ maxLines,
+ ellipsis,
+ constraints)
+}
+
+@OptIn(InternalPlatformTextApi::class)
internal actual fun ActualParagraph(
text: String,
style: TextStyle,
@@ -348,32 +368,32 @@
constraints: ParagraphConstraints,
density: Density,
resourceLoader: Font.ResourceLoader
-): Paragraph {
- return AndroidParagraph(
- text = text,
- style = style,
- spanStyles = spanStyles,
- placeholders = placeholders,
- maxLines = maxLines,
- ellipsis = ellipsis,
- constraints = constraints,
- typefaceAdapter = TypefaceAdapter(
- resourceLoader = resourceLoader
+): Paragraph =
+ @Suppress("DEPRECATION_ERROR")
+ paragraphActualFactory(
+ ActualParagraphIntrinsics(
+ text,
+ style,
+ spanStyles,
+ placeholders,
+ density,
+ resourceLoader
),
- density = density
+ maxLines,
+ ellipsis,
+ constraints
)
-}
+@OptIn(InternalPlatformTextApi::class)
internal actual fun ActualParagraph(
paragraphIntrinsics: ParagraphIntrinsics,
maxLines: Int,
ellipsis: Boolean,
constraints: ParagraphConstraints
-): Paragraph {
- return AndroidParagraph(
- paragraphIntrinsics = paragraphIntrinsics as AndroidParagraphIntrinsics,
- maxLines = maxLines,
- ellipsis = ellipsis,
- constraints = constraints
- )
-}
\ No newline at end of file
+): Paragraph =
+ @Suppress("DEPRECATION_ERROR")
+ paragraphActualFactory(
+ paragraphIntrinsics,
+ maxLines,
+ ellipsis,
+ constraints)
diff --git a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
index 64a7174..97cdc1d 100644
--- a/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
+++ b/ui/ui-text-core/src/androidMain/kotlin/androidx/ui/text/platform/AndroidParagraphIntrinsics.kt
@@ -82,14 +82,21 @@
}
}
-internal actual fun ActualParagraphIntrinsics(
+// TODO(b/159152328): temporary workaround for ui-desktop. remove when full support of MPP will be in-place
+@Deprecated(
+ "Temporary workaround. Supposed to be used only in ui-desktop before MPP",
+ level = DeprecationLevel.ERROR
+)
+@InternalPlatformTextApi
+var paragraphIntrinsicsActualFactory: ((
text: String,
style: TextStyle,
spanStyles: List<AnnotatedString.Range<SpanStyle>>,
placeholders: List<AnnotatedString.Range<Placeholder>>,
density: Density,
resourceLoader: Font.ResourceLoader
-): ParagraphIntrinsics = AndroidParagraphIntrinsics(
+) -> ParagraphIntrinsics) = { text, style, spanStyles, placeholders, density, resourceLoader ->
+ AndroidParagraphIntrinsics(
text = text,
style = style,
placeholders = placeholders,
@@ -98,4 +105,19 @@
),
spanStyles = spanStyles,
density = density
+ )
+}
+
+@OptIn(InternalPlatformTextApi::class)
+internal actual fun ActualParagraphIntrinsics(
+ text: String,
+ style: TextStyle,
+ spanStyles: List<AnnotatedString.Range<SpanStyle>>,
+ placeholders: List<AnnotatedString.Range<Placeholder>>,
+ density: Density,
+ resourceLoader: Font.ResourceLoader
+): ParagraphIntrinsics =
+ @Suppress("DEPRECATION_ERROR")
+ paragraphIntrinsicsActualFactory(
+ text, style, spanStyles, placeholders, density, resourceLoader
)
\ No newline at end of file
diff --git a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
index 39479b2..ecb624c 100644
--- a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/TextRange.kt
@@ -45,6 +45,11 @@
val collapsed: Boolean get() = start == end
/**
+ * Returns true if the start offset is larger than the end offset.
+ */
+ val reversed: Boolean get() = start > end
+
+ /**
* Returns the length of the range.
*/
val length: Int get() = max - min
@@ -82,3 +87,24 @@
* Creates a [TextRange] where start is equal to end, and the value of those are [index].
*/
fun TextRange(index: Int): TextRange = TextRange(start = index, end = index)
+
+/**
+ * Ensures that [TextRange.start] and [TextRange.end] values lies in the specified range
+ * [minimumValue] and [maximumValue]. For each [TextRange.start] and [TextRange.end] values:
+ * - if value is smaller than [minimumValue], value is replaced by [minimumValue]
+ * - if value is greater than [maximumValue], value is replaced by [maximumValue]
+ *
+ * @param minimumValue the minimum value that [TextRange.start] or [TextRange.end] can be.
+ * @param maximumValue the exclusive maximum value that [TextRange.start] or [TextRange.end] can be.
+ *
+ * @suppress
+ */
+@InternalTextApi
+fun TextRange.constrain(minimumValue: Int, maximumValue: Int): TextRange {
+ val newStart = start.coerceIn(minimumValue, maximumValue)
+ val newEnd = end.coerceIn(minimumValue, maximumValue)
+ if (newStart != start || newEnd != end) {
+ return TextRange(newStart, newEnd)
+ }
+ return this
+}
\ No newline at end of file
diff --git a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt
index c74f11b..92761f5 100644
--- a/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt
+++ b/ui/ui-text-core/src/commonMain/kotlin/androidx/ui/text/platform/PlatformParagraph.kt
@@ -54,4 +54,4 @@
placeholders: List<AnnotatedString.Range<Placeholder>>,
density: Density,
resourceLoader: Font.ResourceLoader
-): ParagraphIntrinsics
+): ParagraphIntrinsics
\ No newline at end of file
diff --git a/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt b/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt
index 47b3f90..cb4d375 100644
--- a/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt
+++ b/ui/ui-text-core/src/test/java/androidx/ui/text/TextRangeTest.kt
@@ -21,6 +21,7 @@
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+@OptIn(InternalTextApi::class)
@RunWith(JUnit4::class)
class TextRangeTest {
@Test
@@ -60,6 +61,15 @@
}
@Test
+ fun test_range_reversed() {
+ assertThat(TextRange(0, 0).reversed).isFalse()
+ assertThat(TextRange(0, 1).reversed).isFalse()
+
+ assertThat(TextRange(1, 0).reversed).isTrue()
+ assertThat(TextRange(3, 2).reversed).isTrue()
+ }
+
+ @Test
fun test_intersects() {
// same values intersect
assertThat(TextRange(0, 1).intersects(TextRange(0, 1))).isTrue()
@@ -127,4 +137,37 @@
fun test_does_not_accept_negative_value_for_end() {
TextRange(1, -1)
}
+
+ @Test
+ fun constrain_returns_same_object_if_no_change_required() {
+ val textRange = TextRange(1, 2)
+ assertThat(textRange.constrain(0, 3)).isSameInstanceAs(textRange)
+ }
+
+ @Test
+ fun constrain_updates_start_end_if_required() {
+ assertThat(TextRange(0, 4).constrain(1, 3)).isEqualTo(TextRange(1, 3))
+ }
+
+ @Test
+ fun constrain_collapsed_TextRange_with_the_same_min_max_returns_the_same_instance() {
+ val textRange = TextRange(2, 2)
+ assertThat(textRange.constrain(2, 2)).isSameInstanceAs(textRange)
+ }
+
+ @Test
+ fun constrain_with_collapsed_min_max_returns_collapsed_values() {
+ assertThat(TextRange(1, 2).constrain(2, 2)).isEqualTo(TextRange(2, 2))
+ assertThat(TextRange(2, 3).constrain(2, 2)).isEqualTo(TextRange(2, 2))
+ }
+
+ @Test
+ fun constrain_min_max_greater_than_TextRange_values() {
+ assertThat(TextRange(0, 4).constrain(5, 6)).isEqualTo(TextRange(5, 5))
+ }
+
+ @Test
+ fun constrain_min_smaller_than_TextRange_values() {
+ assertThat(TextRange(5, 6).constrain(0, 4)).isEqualTo(TextRange(4, 4))
+ }
}
\ No newline at end of file
diff --git a/ui/ui-text/api/0.1.0-dev15.txt b/ui/ui-text/api/0.1.0-dev15.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/0.1.0-dev15.txt
+++ b/ui/ui-text/api/0.1.0-dev15.txt
@@ -33,7 +33,7 @@
method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
- field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
}
public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
package androidx.ui.text.selection {
+ public final class MultiWidgetSelectionDelegateKt {
+ }
+
+ public final class TextFieldSelectionDelegateKt {
+ }
+
public final class TextSelectionDelegateKt {
}
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -33,7 +33,7 @@
method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
- field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
}
public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
package androidx.ui.text.selection {
+ public final class MultiWidgetSelectionDelegateKt {
+ }
+
+ public final class TextFieldSelectionDelegateKt {
+ }
+
public final class TextSelectionDelegateKt {
}
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
@@ -33,7 +33,7 @@
method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
- field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
}
public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
package androidx.ui.text.selection {
+ public final class MultiWidgetSelectionDelegateKt {
+ }
+
+ public final class TextFieldSelectionDelegateKt {
+ }
+
public final class TextSelectionDelegateKt {
}
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -33,7 +33,7 @@
method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
- field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
}
public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
package androidx.ui.text.selection {
+ public final class MultiWidgetSelectionDelegateKt {
+ }
+
+ public final class TextFieldSelectionDelegateKt {
+ }
+
public final class TextSelectionDelegateKt {
}
diff --git a/ui/ui-text/api/restricted_0.1.0-dev15.txt b/ui/ui-text/api/restricted_0.1.0-dev15.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev15.txt
@@ -33,7 +33,7 @@
method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
- field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
}
public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
package androidx.ui.text.selection {
+ public final class MultiWidgetSelectionDelegateKt {
+ }
+
+ public final class TextFieldSelectionDelegateKt {
+ }
+
public final class TextSelectionDelegateKt {
}
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index 1c3435f..a9d41e4 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -33,7 +33,7 @@
method public androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> getSupportsInputMethods();
property public final androidx.ui.semantics.SemanticsPropertyKey<androidx.ui.input.ImeAction> ImeAction;
property public final androidx.ui.semantics.SemanticsPropertyKey<java.lang.Boolean> SupportsInputMethods;
- field public static final androidx.ui.text.TextSemanticsProperties! INSTANCE;
+ field public static final androidx.ui.text.TextSemanticsProperties INSTANCE;
}
public final class TextSemanticsPropertiesKt {
@@ -47,6 +47,12 @@
package androidx.ui.text.selection {
+ public final class MultiWidgetSelectionDelegateKt {
+ }
+
+ public final class TextFieldSelectionDelegateKt {
+ }
+
public final class TextSelectionDelegateKt {
}
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/MultiWidgetSelectionDelegateTest.kt
similarity index 96%
rename from ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt
rename to ui/ui-text/src/androidTest/java/androidx/ui/text/selection/MultiWidgetSelectionDelegateTest.kt
index 280605b..97738f1 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextSelectionDelegateTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/MultiWidgetSelectionDelegateTest.kt
@@ -63,7 +63,7 @@
@OptIn(InternalTextApi::class)
@RunWith(JUnit4::class)
@SmallTest
-class TextSelectionDelegateTest {
+class MultiWidgetSelectionDelegateTest {
@get:Rule
val composeTestRule = AndroidComposeTestRule<ComponentActivity>()
@@ -88,13 +88,13 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
)
- val selectableInvalid = TextSelectionDelegate(
+ val selectableInvalid = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { null },
layoutResultCallback = { layoutResult }
@@ -145,13 +145,13 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
)
- val selectableInvalid = TextSelectionDelegate(
+ val selectableInvalid = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { null },
layoutResultCallback = { layoutResult }
@@ -203,7 +203,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -257,7 +257,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -311,7 +311,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -365,7 +365,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -421,7 +421,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -477,7 +477,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -531,7 +531,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -585,7 +585,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -639,7 +639,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -693,7 +693,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -749,7 +749,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -805,7 +805,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -851,7 +851,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -881,7 +881,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = {},
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -909,7 +909,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = mock(),
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -946,7 +946,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = mock(),
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -981,7 +981,7 @@
val layoutCoordinates = mock<LayoutCoordinates>()
whenever(layoutCoordinates.isAttached).thenReturn(true)
- val selectable = TextSelectionDelegate(
+ val selectable = MultiWidgetSelectionDelegate(
selectionRangeUpdate = mock(),
coordinatesCallback = { layoutCoordinates },
layoutResultCallback = { layoutResult }
@@ -1310,7 +1310,7 @@
}
@Test
- fun testTextSelectionProcessor_single_widget_handles_crossed_ltr() {
+ fun getTextSelectionInfo_single_widget_handles_crossed_ltr() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1351,7 +1351,7 @@
}
@Test
- fun testTextSelectionProcessor_single_widget_handles_crossed_rtl() {
+ fun getTextSelectionInfo_single_widget_handles_crossed_rtl() {
with(defaultDensity) {
val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
val fontSize = 20.sp
@@ -1399,7 +1399,7 @@
}
@Test
- fun testTextSelectionProcessor_single_widget_handles_crossed_bidi() {
+ fun getTextSelectionInfo_single_widget_handles_crossed_bidi() {
with(defaultDensity) {
val textLtr = "Hello"
val textRtl = "\u05D0\u05D1\u05D2\u05D3\u05D4"
@@ -1449,7 +1449,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_ltr_drag_endHandle() {
+ fun getTextSelectionInfo_bound_to_one_character_ltr_drag_endHandle() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1505,7 +1505,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_rtl_drag_endHandle() {
+ fun getTextSelectionInfo_bound_to_one_character_rtl_drag_endHandle() {
with(defaultDensity) {
val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
val fontSize = 20.sp
@@ -1567,7 +1567,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_not_crossed() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_not_crossed() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1624,7 +1624,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_crossed() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_crossed() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1681,7 +1681,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_not_crossed_bounded() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_not_crossed_bounded() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1728,7 +1728,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_crossed_bounded() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_crossed_bounded() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1775,7 +1775,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_not_crossed_boundary() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_not_crossed_boundary() {
with(defaultDensity) {
val text = "hello world"
val fontSize = 20.sp
@@ -1824,7 +1824,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_startHandle_crossed_boundary() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_startHandle_crossed_boundary() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1871,7 +1871,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_crossed() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_crossed() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1928,7 +1928,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_not_crossed_bounded() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_not_crossed_bounded() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -1975,7 +1975,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_crossed_bounded() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_crossed_bounded() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -2022,7 +2022,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_not_crossed_boundary() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_not_crossed_boundary() {
with(defaultDensity) {
val text = "hello world"
val fontSize = 20.sp
@@ -2071,7 +2071,7 @@
}
@Test
- fun testTextSelectionProcessor_bound_to_one_character_drag_endHandle_crossed_boundary() {
+ fun getTextSelectionInfo_bound_to_one_character_drag_endHandle_crossed_boundary() {
with(defaultDensity) {
val text = "hello world"
val fontSize = 20.sp
@@ -2120,7 +2120,7 @@
}
@Test
- fun testTextSelectionProcessor_cross_widget_not_contain_start() {
+ fun getTextSelectionInfo_cross_widget_not_contain_start() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
@@ -2160,7 +2160,7 @@
}
@Test
- fun testTextSelectionProcessor_cross_widget_not_contain_end() {
+ fun getTextSelectionInfo_cross_widget_not_contain_end() {
with(defaultDensity) {
val text = "hello world"
val fontSize = 20.sp
@@ -2201,7 +2201,7 @@
}
@Test
- fun testTextSelectionProcessor_cross_widget_not_contain_start_handles_crossed() {
+ fun getTextSelectionInfo_cross_widget_not_contain_start_handles_crossed() {
with(defaultDensity) {
val text = "hello world"
val fontSize = 20.sp
@@ -2243,7 +2243,7 @@
}
@Test
- fun testTextSelectionProcessor_cross_widget_not_contain_end_handles_crossed() {
+ fun getTextSelectionInfo_cross_widget_not_contain_end_handles_crossed() {
with(defaultDensity) {
val text = "hello world"
val fontSize = 20.sp
@@ -2285,7 +2285,7 @@
}
@Test
- fun testTextSelectionProcessor_not_selected() {
+ fun getTextSelectionInfo_not_selected() {
with(defaultDensity) {
val text = "hello world\n"
val fontSize = 20.sp
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextFieldSelectionDelegateTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextFieldSelectionDelegateTest.kt
new file mode 100644
index 0000000..6b6a5e5
--- /dev/null
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/selection/TextFieldSelectionDelegateTest.kt
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.selection
+
+import androidx.activity.ComponentActivity
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.ui.core.Constraints
+import androidx.ui.core.LayoutDirection
+import androidx.ui.test.android.AndroidComposeTestRule
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.InternalTextApi
+import androidx.ui.text.SpanStyle
+import androidx.ui.text.TextDelegate
+import androidx.ui.text.TextLayoutResult
+import androidx.ui.text.TextRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.font.asFontFamily
+import androidx.ui.unit.Density
+import androidx.ui.unit.TextUnit
+import androidx.ui.unit.sp
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(InternalTextApi::class)
+@RunWith(JUnit4::class)
+@SmallTest
+class TextFieldSelectionDelegateTest {
+ @get:Rule
+ val composeTestRule = AndroidComposeTestRule<ComponentActivity>()
+
+ private val fontFamily = BASIC_MEASURE_FONT.asFontFamily()
+ private val context = InstrumentationRegistry.getInstrumentation().context
+ private val defaultDensity = Density(density = 1f)
+ private val resourceLoader = TestFontResourceLoader(context)
+
+ @Test
+ fun getTextFieldSelection_long_press_select_word_ltr() {
+ val text = "hello world\n"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = 2,
+ rawEndOffset = 2,
+ previousSelection = null,
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = true
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(0)
+ Truth.assertThat(range.end).isEqualTo("hello".length)
+ }
+
+ @Test
+ fun getTextFieldSelection_long_press_select_word_rtl() {
+ val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = 5,
+ rawEndOffset = 5,
+ previousSelection = null,
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = true
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(text.indexOf("\u05D3"))
+ Truth.assertThat(range.end).isEqualTo(text.indexOf("\u05D5") + 1)
+ }
+
+ @Test
+ fun getTextFieldSelection_long_press_drag_handle_not_cross_select_word() {
+ val text = "hello world"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ val rawStartOffset = text.indexOf('e')
+ val rawEndOffset = text.indexOf('r')
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = rawStartOffset,
+ rawEndOffset = rawEndOffset,
+ previousSelection = null,
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = true
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(0)
+ Truth.assertThat(range.end).isEqualTo(text.length)
+ }
+
+ @Test
+ fun getTextFieldSelection_long_press_drag_handle_cross_select_word() {
+ val text = "hello world"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ val rawStartOffset = text.indexOf('r')
+ val rawEndOffset = text.indexOf('e')
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = rawStartOffset,
+ rawEndOffset = rawEndOffset,
+ previousSelection = null,
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = true
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(text.length)
+ Truth.assertThat(range.end).isEqualTo(0)
+ }
+
+ @Test
+ fun getTextFieldSelection_drag_select_range_ltr() {
+ val text = "hello world\n"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // "llo wor" is selected.
+ val startOffset = text.indexOf("l")
+ val endOffset = text.indexOf("r") + 1
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = TextRange(0, 0),
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = false
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(startOffset)
+ Truth.assertThat(range.end).isEqualTo(endOffset)
+ }
+
+ @Test
+ fun getTextFieldSelection_drag_select_range_rtl() {
+ val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // "\u05D1\u05D2 \u05D3" is selected.
+ val startOffset = text.indexOf("\u05D1")
+ val endOffset = text.indexOf("\u05D3") + 1
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = TextRange(0, 0),
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = false
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(startOffset)
+ Truth.assertThat(range.end).isEqualTo(endOffset)
+ }
+
+ @Test
+ fun getTextFieldSelection_drag_select_range_bidi() {
+ val textLtr = "Hello"
+ val textRtl = "\u05D0\u05D1\u05D2\u05D3\u05D4"
+ val text = textLtr + textRtl
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // "llo"+"\u05D0\u05D1\u05D2" is selected
+ val startOffset = text.indexOf("l")
+ val endOffset = text.indexOf("\u05D2") + 1
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = TextRange(0, 0),
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = false
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(startOffset)
+ Truth.assertThat(range.end).isEqualTo(endOffset)
+ }
+
+ @Test
+ fun getTextFieldSelection_drag_handles_crossed_ltr() {
+ val text = "hello world\n"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // "llo wor" is selected.
+ val startOffset = text.indexOf("r") + 1
+ val endOffset = text.indexOf("l")
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = TextRange(0, 0),
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = false
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(startOffset)
+ Truth.assertThat(range.end).isEqualTo(endOffset)
+ }
+
+ @Test
+ fun getTextFieldSelection_drag_handles_crossed_rtl() {
+ val text = "\u05D0\u05D1\u05D2 \u05D3\u05D4\u05D5\n"
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // "\u05D1\u05D2 \u05D3" is selected.
+ val startOffset = text.indexOf("\u05D3") + 1
+ val endOffset = text.indexOf("\u05D1")
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = TextRange(0, 0),
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = false
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(startOffset)
+ Truth.assertThat(range.end).isEqualTo(endOffset)
+ }
+
+ @Test
+ fun getTextFieldSelection_drag_handles_crossed_bidi() {
+ val textLtr = "Hello"
+ val textRtl = "\u05D0\u05D1\u05D2\u05D3\u05D4"
+ val text = textLtr + textRtl
+ val fontSize = 20.sp
+
+ val textLayoutResult = simpleTextLayout(
+ text = text,
+ fontSize = fontSize,
+ density = defaultDensity
+ )
+
+ // "llo"+"\u05D0\u05D1\u05D2" is selected
+ val startOffset = text.indexOf("\u05D2") + 1
+ val endOffset = text.indexOf("l")
+
+ // Act.
+ val range = getTextFieldSelection(
+ textLayoutResult = textLayoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = TextRange(0, 0),
+ previousHandlesCrossed = false,
+ isStartHandle = true,
+ wordBasedSelection = false
+ )
+
+ // Assert.
+ Truth.assertThat(range.start).isEqualTo(startOffset)
+ Truth.assertThat(range.end).isEqualTo(endOffset)
+ }
+
+ private fun simpleTextLayout(
+ text: String = "",
+ fontSize: TextUnit = TextUnit.Inherit,
+ density: Density
+ ): TextLayoutResult {
+ val spanStyle = SpanStyle(fontSize = fontSize, fontFamily = fontFamily)
+ val annotatedString = AnnotatedString(text, spanStyle)
+ return TextDelegate(
+ text = annotatedString,
+ style = TextStyle(),
+ density = density,
+ resourceLoader = resourceLoader
+ ).layout(Constraints(), LayoutDirection.Ltr)
+ }
+}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt b/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt
index 7d27dfa..844dc2a 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/CoreText.kt
@@ -40,7 +40,7 @@
import androidx.ui.graphics.drawscope.drawCanvas
import androidx.ui.graphics.Paint
import androidx.ui.text.font.Font
-import androidx.ui.text.selection.TextSelectionDelegate
+import androidx.ui.text.selection.MultiWidgetSelectionDelegate
import androidx.ui.text.style.TextAlign
import androidx.ui.text.style.TextOverflow
import androidx.ui.unit.Density
@@ -242,7 +242,7 @@
val id: Selectable? =
selectionRegistrar?.let {
selectionRegistrar.subscribe(
- TextSelectionDelegate(
+ MultiWidgetSelectionDelegate(
selectionRangeUpdate = { state.selectionRange = it },
coordinatesCallback = { state.layoutCoordinates },
layoutResultCallback = { state.layoutResult }
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt b/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
index e14be9b..0b1cd85 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/CoreTextField.kt
@@ -24,22 +24,26 @@
import androidx.compose.remember
import androidx.compose.setValue
import androidx.compose.state
+import androidx.ui.core.ClipboardManagerAmbient
import androidx.ui.core.DensityAmbient
import androidx.ui.core.FontLoaderAmbient
+import androidx.ui.core.HapticFeedBackAmbient
import androidx.ui.core.Layout
import androidx.ui.core.LayoutCoordinates
import androidx.ui.core.Modifier
-import androidx.ui.core.PassThroughLayout
import androidx.ui.core.TextInputServiceAmbient
import androidx.ui.core.drawBehind
-import androidx.ui.core.gesture.DragObserver
-import androidx.ui.core.gesture.dragGestureFilter
-import androidx.ui.core.gesture.pressIndicatorGestureFilter
import androidx.ui.core.onPositioned
import androidx.ui.core.focus.FocusModifier
import androidx.ui.core.focus.FocusState
import androidx.ui.core.focus.focusState
+import androidx.ui.core.gesture.DragObserver
+import androidx.ui.core.gesture.LongPressDragObserver
+import androidx.ui.core.gesture.dragGestureFilter
+import androidx.ui.core.gesture.longPressDragGestureFilter
+import androidx.ui.core.gesture.pressIndicatorGestureFilter
import androidx.ui.core.semantics.semantics
+import androidx.ui.geometry.Offset
import androidx.ui.graphics.drawscope.drawCanvas
import androidx.ui.input.EditProcessor
import androidx.ui.input.TextFieldValue
@@ -48,7 +52,8 @@
import androidx.ui.input.NO_SESSION
import androidx.ui.input.VisualTransformation
import androidx.ui.semantics.onClick
-import androidx.ui.geometry.Offset
+import androidx.ui.text.selection.TextFieldSelectionManager
+import androidx.ui.text.style.TextDirection
import kotlin.math.roundToInt
@Suppress("DEPRECATION")
@@ -72,14 +77,11 @@
if (fullModel.value.text != value.text ||
fullModel.value.selection != value.selection ||
fullModel.value.composition != value.composition) {
- val newSelection = TextRange(
- value.selection.start.coerceIn(0, value.text.length),
- value.selection.end.coerceIn(0, value.text.length)
- )
+ @OptIn(InternalTextApi::class)
fullModel.value = TextFieldValue(
text = value.text,
- selection = newSelection,
- composition = value.composition
+ selection = value.selection.constrain(0, value.text.length),
+ composition = value.composition?.constrain(0, value.text.length)
)
}
@@ -211,23 +213,20 @@
)
// TODO: Stop lookup FocusModifier from modifier chain. (b/155434146)
- var focusModifier: FocusModifier? = null
- modifier.foldIn(Unit) { _, element ->
- if (element is FocusModifier) {
- focusModifier = element
- return@foldIn
- }
- }
-
- val updatedModifier = if (focusModifier == null) {
- modifier + FocusModifier().also { focusModifier = it }
- } else {
- modifier
- }
+ val focusModifier = chainedFocusModifier(modifier) ?: FocusModifier()
state.processor.onNewState(value, textInputService, state.inputSession)
- TextInputEventObserver(
- focusModifier = focusModifier!!,
+
+ val manager = remember { TextFieldSelectionManager() }
+ manager.offsetMap = offsetMap
+ manager.onValueChange = onValueChangeWrapper
+ manager.state = state
+ manager.value = value
+ manager.clipboardManager = ClipboardManagerAmbient.current
+ manager.hapticFeedBack = HapticFeedBackAmbient.current
+
+ val observer = textInputEventObserver(
+ focusModifier = focusModifier,
onPress = { },
onFocus = {
state.hasFocus = true
@@ -278,79 +277,91 @@
onFocusChange(false)
},
onRelease = {
- state.layoutResult?.let { layoutResult ->
- TextFieldDelegate.onRelease(
- it,
- layoutResult,
- state.processor,
- offsetMap,
- onValueChangeWrapper,
- textInputService,
- state.inputSession,
- state.hasFocus
- )
+ if (state.selectionIsOn == false) {
+ state.layoutResult?.let { layoutResult ->
+ TextFieldDelegate.onRelease(
+ it,
+ layoutResult,
+ state.processor,
+ offsetMap,
+ onValueChangeWrapper,
+ textInputService,
+ state.inputSession,
+ state.hasFocus
+ )
+ }
}
},
+ state = state,
+ longPressDragObserver = manager.longPressDragObserver,
imeAction = imeAction
- ) {
- Layout(
- emptyContent(),
- updatedModifier.drawBehind {
- state.layoutResult?.let { layoutResult ->
- drawCanvas { canvas, _ ->
- TextFieldDelegate.draw(
- canvas,
- value,
- offsetMap,
- layoutResult,
- DefaultSelectionColor
- )
- }
- }
- }.onPositioned {
- if (textInputService != null) {
- state.layoutCoordinates = it
- state.layoutResult?.let { layoutResult ->
- TextFieldDelegate.notifyFocusedRect(
- value,
- state.textDelegate,
- layoutResult,
- it,
- textInputService,
- state.inputSession,
- state.hasFocus,
- offsetMap
- )
- }
- }
+ )
+
+ val drawModifier = Modifier.drawBehind {
+ state.layoutResult?.let { layoutResult ->
+ drawCanvas { canvas, _ ->
+ TextFieldDelegate.draw(
+ canvas,
+ value,
+ offsetMap,
+ layoutResult,
+ DefaultSelectionColor
+ )
}
- ) { _, constraints, layoutDirection ->
- TextFieldDelegate.layout(
- state.textDelegate,
- constraints,
- layoutDirection,
- state.layoutResult
- ).let { (width, height, result) ->
- if (state.layoutResult != result) {
- state.layoutResult = result
- onTextLayout(result)
- }
- layout(
- width,
- height,
- mapOf(
- FirstBaseline to result.firstBaseline.roundToInt(),
- LastBaseline to result.lastBaseline.roundToInt()
- )
- ) {}
+ }
+ }
+
+ val onPositionedModifier = Modifier.onPositioned {
+ if (textInputService != null) {
+ state.layoutCoordinates = it
+ state.layoutResult?.let { layoutResult ->
+ TextFieldDelegate.notifyFocusedRect(
+ value,
+ state.textDelegate,
+ layoutResult,
+ it,
+ textInputService,
+ state.inputSession,
+ state.hasFocus,
+ offsetMap
+ )
}
}
}
+
+ Layout(
+ emptyContent(),
+ modifier
+ .plus(observer)
+ .plus(focusModifier)
+ .plus(drawModifier)
+ .plus(onPositionedModifier)
+ ) { _, constraints, layoutDirection ->
+ TextFieldDelegate.layout(
+ state.textDelegate,
+ constraints,
+ layoutDirection,
+ state.layoutResult
+ ).let { (width, height, result) ->
+ if (state.layoutResult != result) {
+ state.layoutResult = result
+ onTextLayout(result)
+ }
+ layout(
+ width,
+ height,
+ mapOf(
+ FirstBaseline to result.firstBaseline.roundToInt(),
+ LastBaseline to result.lastBaseline.roundToInt()
+ )
+ ) {}
+ }
+ }
}
}
@OptIn(InternalTextApi::class)
-private class TextFieldState(
+internal class TextFieldState(
var textDelegate: TextDelegate
) {
val processor = EditProcessor()
@@ -364,21 +375,48 @@
var layoutCoordinates: LayoutCoordinates? = null
/** The latest TextLayoutResult calculated in the measure block */
var layoutResult: TextLayoutResult? = null
+ /**
+ * The gesture detector status, to indicate whether current status is selection or editing.
+ *
+ * In the editing mode, there is no selection shown, only cursor is shown. To enter the editing
+ * mode from selection mode, just tap on the screen.
+ *
+ * In the selection mode, there is no cursor shown, only selection is shown. To enter
+ * the selection mode, just long press on the screen. In this mode, finger movement on the
+ * screen changes selection instead of moving the cursor.
+ */
+ var selectionIsOn: Boolean = false
+ /** The [TextDirection] for the start of the selection. */
+ var selectionStartDirection: TextDirection = TextDirection.Ltr
+ /** The [TextDirection] for the end of the selection. */
+ var selectionEndDirection: TextDirection = TextDirection.Ltr
+}
+
+private fun chainedFocusModifier(modifier: Modifier): FocusModifier? {
+ var focusModifier: FocusModifier? = null
+ modifier.foldIn(Unit) { _, element ->
+ if (element is FocusModifier) {
+ focusModifier = element
+ return@foldIn
+ }
+ }
+ return focusModifier
}
/**
* Helper composable for observing all text input related events.
*/
@Composable
-private fun TextInputEventObserver(
+private fun textInputEventObserver(
onPress: (Offset) -> Unit,
onRelease: (Offset) -> Unit,
onFocus: () -> Unit,
+ state: TextFieldState,
+ longPressDragObserver: LongPressDragObserver,
onBlur: (hasNextClient: Boolean) -> Unit,
focusModifier: FocusModifier,
- imeAction: ImeAction,
- children: @Composable () -> Unit
-) {
+ imeAction: ImeAction
+): Modifier {
val prevState = state { FocusState.NotFocused }
if (focusModifier.focusState == FocusState.Focused &&
prevState.value == FocusState.NotFocused
@@ -404,8 +442,7 @@
onBlur(false)
}
- val semantics = Modifier.semantics(applyToChildLayoutNode = true,
- mergeAllDescendants = true,
+ val semantics = Modifier.semantics(mergeAllDescendants = true,
properties = {
this.imeAction = imeAction
this.supportsInputMethods = true
@@ -413,22 +450,18 @@
})
val drag = Modifier.dragPositionGestureFilter(
onPress = {
+ state.selectionIsOn = false
if (focusModifier.focusState == FocusState.Focused) {
onPress(it)
} else {
doFocusIn()
}
},
- onRelease = onRelease
+ onRelease = onRelease,
+ longPressDragObserver = longPressDragObserver
)
- // TODO(b/150706555): This layout is temporary and should be removed once Semantics
- // is implemented with modifiers.
- @Suppress("DEPRECATION")
- PassThroughLayout(semantics) {
- @Suppress("DEPRECATION")
- PassThroughLayout(drag, children)
- }
+ return semantics.plus(drag)
}
/**
@@ -472,7 +505,8 @@
@Composable
private fun Modifier.dragPositionGestureFilter(
onPress: (Offset) -> Unit,
- onRelease: (Offset) -> Unit
+ onRelease: (Offset) -> Unit,
+ longPressDragObserver: LongPressDragObserver
): Modifier {
val tracker = state { DragEventTracker() }
// TODO(shepshapard): PressIndicator doesn't seem to be the right thing to use here. It
@@ -494,4 +528,5 @@
return Offset.Zero
}
})
+ .longPressDragGestureFilter(longPressDragObserver)
}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/MultiWidgetSelectionDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/MultiWidgetSelectionDelegate.kt
new file mode 100644
index 0000000..a06b97b
--- /dev/null
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/MultiWidgetSelectionDelegate.kt
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.selection
+
+import androidx.ui.core.LayoutCoordinates
+import androidx.ui.core.selection.Selectable
+import androidx.ui.core.selection.Selection
+import androidx.ui.geometry.Offset
+import androidx.ui.geometry.Rect
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.TextLayoutResult
+import androidx.ui.text.TextRange
+import kotlin.math.max
+
+internal class MultiWidgetSelectionDelegate(
+ private val selectionRangeUpdate: (TextRange?) -> Unit,
+ private val coordinatesCallback: () -> LayoutCoordinates?,
+ private val layoutResultCallback: () -> TextLayoutResult?
+) : Selectable {
+ override fun getSelection(
+ startPosition: Offset,
+ endPosition: Offset,
+ containerLayoutCoordinates: LayoutCoordinates,
+ longPress: Boolean,
+ previousSelection: Selection?,
+ isStartHandle: Boolean
+ ): Selection? {
+ val layoutCoordinates = getLayoutCoordinates() ?: return null
+ val textLayoutResult = layoutResultCallback() ?: return null
+
+ val relativePosition = containerLayoutCoordinates.childToLocal(
+ layoutCoordinates, Offset.Zero
+ )
+ val startPx = startPosition - relativePosition
+ val endPx = endPosition - relativePosition
+
+ val selection = getTextSelectionInfo(
+ textLayoutResult = textLayoutResult,
+ selectionCoordinates = Pair(startPx, endPx),
+ selectable = this,
+ wordBasedSelection = longPress,
+ previousSelection = previousSelection,
+ isStartHandle = isStartHandle
+ )
+
+ return if (selection == null) {
+ selectionRangeUpdate(null)
+ null
+ } else {
+ selectionRangeUpdate(selection.toTextRange())
+ return selection
+ }
+ }
+
+ override fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset {
+ // Check if the selection handles's selectable is the current selectable.
+ if (isStartHandle && selection.start.selectable != this ||
+ !isStartHandle && selection.end.selectable != this) {
+ return Offset.Zero
+ }
+
+ if (getLayoutCoordinates() == null) return Offset.Zero
+
+ val textLayoutResult = layoutResultCallback() ?: return Offset.Zero
+ return getSelectionHandleCoordinates(
+ textLayoutResult = textLayoutResult,
+ offset = if (isStartHandle) selection.start.offset else selection.end.offset,
+ isStart = isStartHandle,
+ areHandlesCrossed = selection.handlesCrossed
+ )
+ }
+
+ override fun getLayoutCoordinates(): LayoutCoordinates? {
+ val layoutCoordinates = coordinatesCallback()
+ if (layoutCoordinates == null || !layoutCoordinates.isAttached) return null
+ return layoutCoordinates
+ }
+
+ override fun getText(): AnnotatedString {
+ val textLayoutResult = layoutResultCallback() ?: return AnnotatedString("")
+ return textLayoutResult.layoutInput.text
+ }
+
+ override fun getBoundingBox(offset: Int): Rect {
+ val textLayoutResult = layoutResultCallback() ?: return Rect.zero
+ return textLayoutResult.getBoundingBox(
+ offset.coerceIn(
+ 0,
+ textLayoutResult.layoutInput.text.text.length - 1
+ )
+ )
+ }
+}
+
+/**
+ * Return information about the current selection in the Text.
+ *
+ * @param textLayoutResult a result of the text layout.
+ * @param selectionCoordinates The positions of the start and end of the selection in Text
+ * composable coordinate system.
+ * @param selectable current [Selectable] for which the [Selection] is being calculated
+ * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
+ * the selection is modified by long press and drag gesture, the result selection will be
+ * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
+ * selection.
+ * @param previousSelection previous selection result
+ * @param isStartHandle true if the start handle is being dragged
+ *
+ * @return [Selection] of the current composable, or null if the composable is not selected.
+ */
+internal fun getTextSelectionInfo(
+ textLayoutResult: TextLayoutResult,
+ selectionCoordinates: Pair<Offset, Offset>,
+ selectable: Selectable,
+ wordBasedSelection: Boolean,
+ previousSelection: Selection? = null,
+ isStartHandle: Boolean = true
+): Selection? {
+ val startPosition = selectionCoordinates.first
+ val endPosition = selectionCoordinates.second
+
+ val bounds = Rect(
+ 0.0f,
+ 0.0f,
+ textLayoutResult.size.width.toFloat(),
+ textLayoutResult.size.height.toFloat()
+ )
+
+ val lastOffset = textLayoutResult.layoutInput.text.text.length
+
+ val containsWholeSelectionStart =
+ bounds.contains(Offset(startPosition.x, startPosition.y))
+
+ val containsWholeSelectionEnd =
+ bounds.contains(Offset(endPosition.x, endPosition.y))
+
+ val rawStartOffset =
+ if (containsWholeSelectionStart)
+ textLayoutResult.getOffsetForPosition(startPosition).coerceIn(0, lastOffset)
+ else
+ // If the composable is selected, the start offset cannot be -1 for this composable. If the
+ // final start offset is still -1, it means this composable is not selected.
+ -1
+ val rawEndOffset =
+ if (containsWholeSelectionEnd)
+ textLayoutResult.getOffsetForPosition(endPosition).coerceIn(0, lastOffset)
+ else
+ // If the composable is selected, the end offset cannot be -1 for this composable. If the
+ // final end offset is still -1, it means this composable is not selected.
+ -1
+
+ return getRefinedSelectionInfo(
+ rawStartOffset = rawStartOffset,
+ rawEndOffset = rawEndOffset,
+ containsWholeSelectionStart = containsWholeSelectionStart,
+ containsWholeSelectionEnd = containsWholeSelectionEnd,
+ startPosition = startPosition,
+ endPosition = endPosition,
+ bounds = bounds,
+ textLayoutResult = textLayoutResult,
+ lastOffset = lastOffset,
+ selectable = selectable,
+ wordBasedSelection = wordBasedSelection,
+ previousSelection = previousSelection,
+ isStartHandle = isStartHandle
+ )
+}
+
+/**
+ * This method refines the selection info by processing the initial raw selection info.
+ *
+ * @param rawStartOffset unprocessed start offset calculated directly from input position
+ * @param rawEndOffset unprocessed end offset calculated directly from input position
+ * @param containsWholeSelectionStart a flag to check if current composable contains the overall
+ * selection start
+ * @param containsWholeSelectionEnd a flag to check if current composable contains the overall
+ * selection end
+ * @param startPosition graphical position of the start of the selection, in composable's
+ * coordinates.
+ * @param endPosition graphical position of the end of the selection, in composable's coordinates.
+ * @param bounds bounds of the current composable
+ * @param textLayoutResult a result of the text layout.
+ * @param lastOffset last offset of the text. It's actually the length of the text.
+ * @param selectable current [Selectable] for which the [Selection] is being calculated
+ * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
+ * the selection is modified by long press and drag gesture, the result selection will be
+ * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
+ * selection.
+ * @param previousSelection previous selection result
+ * @param isStartHandle true if the start handle is being dragged
+ *
+ * @return [Selection] of the current composable, or null if the composable is not selected.
+ */
+private fun getRefinedSelectionInfo(
+ rawStartOffset: Int,
+ rawEndOffset: Int,
+ containsWholeSelectionStart: Boolean,
+ containsWholeSelectionEnd: Boolean,
+ startPosition: Offset,
+ endPosition: Offset,
+ bounds: Rect,
+ textLayoutResult: TextLayoutResult,
+ lastOffset: Int,
+ selectable: Selectable,
+ wordBasedSelection: Boolean,
+ previousSelection: Selection? = null,
+ isStartHandle: Boolean = true
+): Selection? {
+ val shouldProcessAsSinglecomposable =
+ containsWholeSelectionStart && containsWholeSelectionEnd
+
+ var (startOffset, endOffset, handlesCrossed) =
+ if (shouldProcessAsSinglecomposable) {
+ processAsSingleComposable(
+ rawStartOffset = rawStartOffset,
+ rawEndOffset = rawEndOffset,
+ previousSelection = previousSelection?.toTextRange(),
+ isStartHandle = isStartHandle,
+ lastOffset = lastOffset,
+ handlesCrossed = previousSelection?.handlesCrossed ?: false
+ )
+ } else {
+ processCrossComposable(
+ startPosition = startPosition,
+ endPosition = endPosition,
+ rawStartOffset = rawStartOffset,
+ rawEndOffset = rawEndOffset,
+ lastOffset = lastOffset,
+ bounds = bounds,
+ containsWholeSelectionStart = containsWholeSelectionStart,
+ containsWholeSelectionEnd = containsWholeSelectionEnd
+ )
+ }
+ // nothing is selected
+ if (startOffset == -1 && endOffset == -1) return null
+
+ // If under long press, update the selection to word-based.
+ if (wordBasedSelection) {
+ val (start, end) = updateWordBasedSelection(
+ textLayoutResult = textLayoutResult,
+ startOffset = startOffset,
+ endOffset = endOffset,
+ handlesCrossed = handlesCrossed
+ )
+ startOffset = start
+ endOffset = end
+ }
+
+ return getAssembledSelectionInfo(
+ startOffset = startOffset,
+ endOffset = endOffset,
+ handlesCrossed = handlesCrossed,
+ selectable = selectable,
+ textLayoutResult = textLayoutResult
+ )
+}
+
+/**
+ * [Selection] contains a lot of parameters. It looks more clean to assemble an object of this
+ * class in a separate method.
+ *
+ * @param startOffset the final start offset to be returned.
+ * @param endOffset the final end offset to be returned.
+ * @param handlesCrossed true if the selection handles are crossed
+ * @param selectable current [Selectable] for which the [Selection] is being calculated
+ * @param textLayoutResult a result of the text layout.
+ *
+ * @return an assembled object of [Selection] using the offered selection info.
+ */
+private fun getAssembledSelectionInfo(
+ startOffset: Int,
+ endOffset: Int,
+ handlesCrossed: Boolean,
+ selectable: Selectable,
+ textLayoutResult: TextLayoutResult
+): Selection {
+ return Selection(
+ start = Selection.AnchorInfo(
+ direction = textLayoutResult.getBidiRunDirection(startOffset),
+ offset = startOffset,
+ selectable = selectable
+ ),
+ end = Selection.AnchorInfo(
+ direction = textLayoutResult.getBidiRunDirection(max(endOffset - 1, 0)),
+ offset = endOffset,
+ selectable = selectable
+ ),
+ handlesCrossed = handlesCrossed
+ )
+}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionDelegate.kt
new file mode 100644
index 0000000..7f6b907
--- /dev/null
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionDelegate.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.selection
+
+import androidx.ui.text.TextLayoutResult
+import androidx.ui.text.TextRange
+
+/**
+ * Return selection information for TextField.
+ *
+ * @param textLayoutResult a result of the text layout.
+ * @param rawStartOffset unprocessed start offset calculated directly from input position
+ * @param rawEndOffset unprocessed end offset calculated directly from input position
+ * @param previousSelection previous selection result
+ * @param previousHandlesCrossed true if the previous selection's handles are crossed
+ * @param isStartHandle true if the start handle is being dragged
+ * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
+ * the selection is modified by long press and drag gesture, the result selection will be
+ * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
+ * selection.
+ *
+ * @return selected text range.
+ */
+internal fun getTextFieldSelection(
+ textLayoutResult: TextLayoutResult?,
+ rawStartOffset: Int,
+ rawEndOffset: Int,
+ previousSelection: TextRange?,
+ previousHandlesCrossed: Boolean,
+ isStartHandle: Boolean,
+ wordBasedSelection: Boolean
+): TextRange {
+ textLayoutResult?.let {
+ val lastOffset = it.layoutInput.text.text.length
+
+ var (startOffset, endOffset, handlesCrossed) =
+ processAsSingleComposable(
+ rawStartOffset = rawStartOffset,
+ rawEndOffset = rawEndOffset,
+ previousSelection = previousSelection,
+ isStartHandle = isStartHandle,
+ lastOffset = lastOffset,
+ handlesCrossed = previousHandlesCrossed
+ )
+ if (wordBasedSelection) {
+ val (start, end) = updateWordBasedSelection(
+ textLayoutResult = it,
+ startOffset = startOffset,
+ endOffset = endOffset,
+ handlesCrossed = handlesCrossed
+ )
+ startOffset = start
+ endOffset = end
+ }
+
+ return TextRange(startOffset, endOffset)
+ }
+ return TextRange(0, 0)
+}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionManager.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionManager.kt
new file mode 100644
index 0000000..61de1f9
--- /dev/null
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextFieldSelectionManager.kt
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.selection
+
+import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.gesture.LongPressDragObserver
+import androidx.ui.core.hapticfeedback.HapticFeedback
+import androidx.ui.core.hapticfeedback.HapticFeedbackType
+import androidx.ui.geometry.Offset
+import androidx.ui.input.OffsetMap
+import androidx.ui.input.TextFieldValue
+import androidx.ui.input.getSelectedText
+import androidx.ui.input.getTextAfterSelection
+import androidx.ui.input.getTextBeforeSelection
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.TextFieldState
+import androidx.ui.text.TextRange
+import kotlin.math.max
+
+/**
+ * A bridge class between user interaction to the text field selection.
+ */
+internal class TextFieldSelectionManager {
+
+ /**
+ * The current [OffsetMap] for text field.
+ */
+ internal var offsetMap: OffsetMap = OffsetMap.identityOffsetMap
+
+ /**
+ * Called when the input service updates the values in [TextFieldValue].
+ */
+ internal var onValueChange: (TextFieldValue) -> Unit = {}
+
+ /**
+ * The current [TextFieldState].
+ */
+ internal var state: TextFieldState? = null
+
+ /**
+ * The current [TextFieldValue].
+ */
+ internal var value: TextFieldValue = TextFieldValue()
+
+ /**
+ * [ClipboardManager] to perform clipboard features.
+ */
+ internal var clipboardManager: ClipboardManager? = null
+
+ /**
+ * [HapticFeedback] handle to perform haptic feedback.
+ */
+ var hapticFeedBack: HapticFeedback? = null
+
+ /**
+ * The beginning position of the drag gesture. Every time a new drag gesture starts, it wil be
+ * recalculated.
+ */
+ private var dragBeginPosition = Offset.Zero
+
+ /**
+ * The total distance being dragged of the drag gesture. Every time a new drag gesture starts,
+ * it will be zeroed out.
+ */
+ private var dragTotalDistance = Offset.Zero
+
+ /**
+ * [LongPressDragObserver] for long press and drag to select in TextField.
+ */
+ internal val longPressDragObserver = object : LongPressDragObserver {
+ override fun onLongPress(pxPosition: Offset) {
+ // selection never started
+ if (value.text == "") return
+ setSelectionStatus(true)
+ state?.layoutResult?.let { layoutResult ->
+ val offset = offsetMap.transformedToOriginal(
+ layoutResult.getOffsetForPosition(pxPosition)
+ )
+ updateSelection(
+ value = value,
+ startOffset = offset,
+ endOffset = offset,
+ isStartHandle = true,
+ wordBasedSelection = true
+ )
+ }
+ dragBeginPosition = pxPosition
+ dragTotalDistance = Offset.Zero
+ }
+
+ override fun onDrag(dragDistance: Offset): Offset {
+ // selection never started, did not consume any drag
+ if (value.text == "") return Offset.Zero
+
+ dragTotalDistance += dragDistance
+ state?.layoutResult?.let { layoutResult ->
+ val startOffset = layoutResult.getOffsetForPosition(dragBeginPosition)
+ val endOffset =
+ layoutResult.getOffsetForPosition(dragBeginPosition + dragTotalDistance)
+ updateSelection(
+ value = value,
+ startOffset = startOffset,
+ endOffset = endOffset,
+ isStartHandle = true,
+ wordBasedSelection = true
+ )
+ }
+ return dragDistance
+ }
+ }
+
+ /**
+ * The method for copying text.
+ *
+ * If there is no selection, return.
+ * Put the selected text into the [ClipboardManager], and cancel the selection.
+ * The text in the text field should be unchanged.
+ * The new cursor offset should be at the end of the previous selected text.
+ */
+ internal fun copy() {
+ if (value.selection.collapsed) return
+
+ clipboardManager?.setText(AnnotatedString(value.getSelectedText()))
+
+ val newCursorOffset = value.selection.end
+ val newValue = TextFieldValue(
+ text = value.text,
+ selection = TextRange(newCursorOffset, newCursorOffset)
+ )
+ onValueChange(newValue)
+ updateTextDirections(TextRange(newCursorOffset, newCursorOffset))
+ setSelectionStatus(false)
+ }
+
+ /**
+ * The method for pasting text.
+ *
+ * Get the text from [ClipboardManager]. If it's null, return.
+ * The new text should be the text before the selected text, plus the text from the
+ * [ClipboardManager], and plus the text after the selected text.
+ * Then the selection should collapse, and the new cursor offset should be the end of the
+ * newly added text.
+ */
+ internal fun paste() {
+ val text = clipboardManager?.getText()?.text ?: return
+
+ val newText = value.getTextBeforeSelection(value.text.length) +
+ text +
+ value.getTextAfterSelection(value.text.length)
+ val newCursorOffset = value.selection.start + text.length
+
+ val newValue = TextFieldValue(
+ text = newText,
+ selection = TextRange(newCursorOffset, newCursorOffset)
+ )
+ onValueChange(newValue)
+ updateTextDirections(TextRange(newCursorOffset, newCursorOffset))
+ setSelectionStatus(false)
+ }
+
+ /**
+ * The method for cutting text.
+ *
+ * If there is no selection, return.
+ * Put the selected text into the [ClipboardManager].
+ * The new text should be the text before the selection plus the text after the selection.
+ * And the new cursor offset should be between the text before the selection, and the text
+ * after the selection.
+ */
+ internal fun cut() {
+ if (value.selection.collapsed) return
+
+ clipboardManager?.setText(AnnotatedString(value.getSelectedText()))
+
+ val newText = value.getTextBeforeSelection(value.text.length) +
+ value.getTextAfterSelection(value.text.length)
+ val newCursorOffset = value.selection.start
+
+ val newValue = TextFieldValue(
+ text = newText,
+ selection = TextRange(newCursorOffset, newCursorOffset)
+ )
+ onValueChange(newValue)
+ updateTextDirections(TextRange(newCursorOffset, newCursorOffset))
+ setSelectionStatus(false)
+ }
+
+ private fun updateSelection(
+ value: TextFieldValue,
+ startOffset: Int,
+ endOffset: Int,
+ isStartHandle: Boolean,
+ wordBasedSelection: Boolean
+ ) {
+ val range = getTextFieldSelection(
+ textLayoutResult = state?.layoutResult,
+ rawStartOffset = startOffset,
+ rawEndOffset = endOffset,
+ previousSelection = if (value.selection.collapsed) null else value.selection,
+ previousHandlesCrossed = value.selection.reversed,
+ isStartHandle = isStartHandle,
+ wordBasedSelection = wordBasedSelection
+ )
+
+ if (range == value.selection) return
+
+ hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
+
+ val newValue = TextFieldValue(
+ text = value.text,
+ selection = range
+ )
+ onValueChange(newValue)
+ updateTextDirections(range)
+ }
+
+ private fun updateTextDirections(range: TextRange) {
+ state?.let {
+ it.selectionStartDirection = it.layoutResult!!.getBidiRunDirection(range.start)
+ it.selectionEndDirection = it.layoutResult!!.getBidiRunDirection(max(range.end - 1, 0))
+ }
+ }
+
+ private fun setSelectionStatus(on: Boolean) {
+ state?.let {
+ it.selectionIsOn = on
+ }
+ }
+}
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt
index 5c56458..c26690a 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/selection/TextSelectionDelegate.kt
@@ -16,292 +16,12 @@
package androidx.ui.text.selection
-import androidx.ui.core.LayoutCoordinates
-import androidx.ui.core.selection.Selectable
-import androidx.ui.core.selection.Selection
import androidx.ui.geometry.Rect
-import androidx.ui.text.AnnotatedString
import androidx.ui.text.TextLayoutResult
import androidx.ui.text.TextRange
import androidx.ui.geometry.Offset
import kotlin.math.max
-internal class TextSelectionDelegate(
- private val selectionRangeUpdate: (TextRange?) -> Unit,
- private val coordinatesCallback: () -> LayoutCoordinates?,
- private val layoutResultCallback: () -> TextLayoutResult?
-) : Selectable {
- override fun getSelection(
- startPosition: Offset,
- endPosition: Offset,
- containerLayoutCoordinates: LayoutCoordinates,
- longPress: Boolean,
- previousSelection: Selection?,
- isStartHandle: Boolean
- ): Selection? {
- val layoutCoordinates = getLayoutCoordinates() ?: return null
- val textLayoutResult = layoutResultCallback() ?: return null
-
- val relativePosition = containerLayoutCoordinates.childToLocal(
- layoutCoordinates, Offset.Zero
- )
- val startPx = startPosition - relativePosition
- val endPx = endPosition - relativePosition
-
- val selection = getTextSelectionInfo(
- textLayoutResult = textLayoutResult,
- selectionCoordinates = Pair(startPx, endPx),
- selectable = this,
- wordBasedSelection = longPress,
- previousSelection = previousSelection,
- isStartHandle = isStartHandle
- )
-
- return if (selection == null) {
- selectionRangeUpdate(null)
- null
- } else {
- selectionRangeUpdate(selection.toTextRange())
- return selection
- }
- }
-
- override fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset {
- // Check if the selection handles's selectable is the current selectable.
- if (isStartHandle && selection.start.selectable != this ||
- !isStartHandle && selection.end.selectable != this) {
- return Offset.Zero
- }
-
- if (getLayoutCoordinates() == null) return Offset.Zero
-
- val textLayoutResult = layoutResultCallback() ?: return Offset.Zero
- return getSelectionHandleCoordinates(
- textLayoutResult = textLayoutResult,
- offset = if (isStartHandle) selection.start.offset else selection.end.offset,
- isStart = isStartHandle,
- areHandlesCrossed = selection.handlesCrossed
- )
- }
-
- override fun getLayoutCoordinates(): LayoutCoordinates? {
- val layoutCoordinates = coordinatesCallback()
- if (layoutCoordinates == null || !layoutCoordinates.isAttached) return null
- return layoutCoordinates
- }
-
- override fun getText(): AnnotatedString {
- val textLayoutResult = layoutResultCallback() ?: return AnnotatedString("")
- return textLayoutResult.layoutInput.text
- }
-
- override fun getBoundingBox(offset: Int): Rect {
- val textLayoutResult = layoutResultCallback() ?: return Rect.zero
- return textLayoutResult.getBoundingBox(
- offset.coerceIn(
- 0,
- textLayoutResult.layoutInput.text.text.length - 1
- )
- )
- }
-}
-
-/**
- * Return information about the current selection in the Text.
- *
- * @param textLayoutResult a result of the text layout.
- * @param selectionCoordinates The positions of the start and end of the selection in Text
- * composable coordinate system.
- * @param selectable current [Selectable] for which the [Selection] is being calculated
- * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
- * the selection is modified by long press and drag gesture, the result selection will be
- * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
- * selection.
- * @param previousSelection previous selection result
- * @param isStartHandle true if the start handle is being dragged
- *
- * @return [Selection] of the current composable, or null if the composable is not selected.
- */
-internal fun getTextSelectionInfo(
- textLayoutResult: TextLayoutResult,
- selectionCoordinates: Pair<Offset, Offset>,
- selectable: Selectable,
- wordBasedSelection: Boolean,
- previousSelection: Selection? = null,
- isStartHandle: Boolean = true
-): Selection? {
- val startPosition = selectionCoordinates.first
- val endPosition = selectionCoordinates.second
-
- val bounds = Rect(
- 0.0f,
- 0.0f,
- textLayoutResult.size.width.toFloat(),
- textLayoutResult.size.height.toFloat()
- )
-
- val lastOffset = textLayoutResult.layoutInput.text.text.length
-
- val containsWholeSelectionStart =
- bounds.contains(Offset(startPosition.x, startPosition.y))
-
- val containsWholeSelectionEnd =
- bounds.contains(Offset(endPosition.x, endPosition.y))
-
- val rawStartOffset =
- if (containsWholeSelectionStart)
- textLayoutResult.getOffsetForPosition(startPosition).coerceIn(0, lastOffset)
- else
- // If the composable is selected, the start offset cannot be -1 for this composable. If the
- // final start offset is still -1, it means this composable is not selected.
- -1
- val rawEndOffset =
- if (containsWholeSelectionEnd)
- textLayoutResult.getOffsetForPosition(endPosition).coerceIn(0, lastOffset)
- else
- // If the composable is selected, the end offset cannot be -1 for this composable. If the
- // final end offset is still -1, it means this composable is not selected.
- -1
-
- return getRefinedSelectionInfo(
- rawStartOffset = rawStartOffset,
- rawEndOffset = rawEndOffset,
- containsWholeSelectionStart = containsWholeSelectionStart,
- containsWholeSelectionEnd = containsWholeSelectionEnd,
- startPosition = startPosition,
- endPosition = endPosition,
- bounds = bounds,
- textLayoutResult = textLayoutResult,
- lastOffset = lastOffset,
- selectable = selectable,
- wordBasedSelection = wordBasedSelection,
- previousSelection = previousSelection,
- isStartHandle = isStartHandle
- )
-}
-
-/**
- * This method refines the selection info by processing the initial raw selection info.
- *
- * @param rawStartOffset unprocessed start offset calculated directly from input position
- * @param rawEndOffset unprocessed end offset calculated directly from input position
- * @param containsWholeSelectionStart a flag to check if current composable contains the overall
- * selection start
- * @param containsWholeSelectionEnd a flag to check if current composable contains the overall
- * selection end
- * @param startPosition graphical position of the start of the selection, in composable's
- * coordinates.
- * @param endPosition graphical position of the end of the selection, in composable's coordinates.
- * @param bounds bounds of the current composable
- * @param textLayoutResult a result of the text layout.
- * @param lastOffset last offset of the text. It's actually the length of the text.
- * @param selectable current [Selectable] for which the [Selection] is being calculated
- * @param wordBasedSelection This flag is ignored if the selection handles are being dragged. If
- * the selection is modified by long press and drag gesture, the result selection will be
- * adjusted to word based selection. Otherwise, the selection will be adjusted to character based
- * selection.
- * @param previousSelection previous selection result
- * @param isStartHandle true if the start handle is being dragged
- *
- * @return [Selection] of the current composable, or null if the composable is not selected.
- */
-private fun getRefinedSelectionInfo(
- rawStartOffset: Int,
- rawEndOffset: Int,
- containsWholeSelectionStart: Boolean,
- containsWholeSelectionEnd: Boolean,
- startPosition: Offset,
- endPosition: Offset,
- bounds: Rect,
- textLayoutResult: TextLayoutResult,
- lastOffset: Int,
- selectable: Selectable,
- wordBasedSelection: Boolean,
- previousSelection: Selection? = null,
- isStartHandle: Boolean = true
-): Selection? {
- val shouldProcessAsSinglecomposable =
- containsWholeSelectionStart && containsWholeSelectionEnd
-
- var (startOffset, endOffset, handlesCrossed) =
- if (shouldProcessAsSinglecomposable) {
- processAsSingleComposable(
- rawStartOffset = rawStartOffset,
- rawEndOffset = rawEndOffset,
- previousSelection = previousSelection,
- isStartHandle = isStartHandle,
- lastOffset = lastOffset
- )
- } else {
- processCrossComposable(
- startPosition = startPosition,
- endPosition = endPosition,
- rawStartOffset = rawStartOffset,
- rawEndOffset = rawEndOffset,
- lastOffset = lastOffset,
- bounds = bounds,
- containsWholeSelectionStart = containsWholeSelectionStart,
- containsWholeSelectionEnd = containsWholeSelectionEnd
- )
- }
- // nothing is selected
- if (startOffset == -1 && endOffset == -1) return null
-
- // If under long press, update the selection to word-based.
- if (wordBasedSelection) {
- val (start, end) = updateWordBasedSelection(
- textLayoutResult = textLayoutResult,
- startOffset = startOffset,
- endOffset = endOffset,
- handlesCrossed = handlesCrossed
- )
- startOffset = start
- endOffset = end
- }
-
- return getAssembledSelectionInfo(
- startOffset = startOffset,
- endOffset = endOffset,
- handlesCrossed = handlesCrossed,
- selectable = selectable,
- textLayoutResult = textLayoutResult
- )
-}
-
-/**
- * [Selection] contains a lot of parameters. It looks more clean to assemble an object of this
- * class in a separate method.
- *
- * @param startOffset the final start offset to be returned.
- * @param endOffset the final end offset to be returned.
- * @param handlesCrossed true if the selection handles are crossed
- * @param selectable current [Selectable] for which the [Selection] is being calculated
- * @param textLayoutResult a result of the text layout.
- *
- * @return an assembled object of [Selection] using the offered selection info.
- */
-private fun getAssembledSelectionInfo(
- startOffset: Int,
- endOffset: Int,
- handlesCrossed: Boolean,
- selectable: Selectable,
- textLayoutResult: TextLayoutResult
-): Selection {
- return Selection(
- start = Selection.AnchorInfo(
- direction = textLayoutResult.getBidiRunDirection(startOffset),
- offset = startOffset,
- selectable = selectable
- ),
- end = Selection.AnchorInfo(
- direction = textLayoutResult.getBidiRunDirection(max(endOffset - 1, 0)),
- offset = endOffset,
- selectable = selectable
- ),
- handlesCrossed = handlesCrossed
- )
-}
-
/**
* This method takes unprocessed selection information as input, and calculates the selection
* range and check if the selection handles are crossed, for selection with both start and end
@@ -312,28 +32,34 @@
* different location. If the selection anchors point the same location and this is true, the
* result selection will be adjusted to word boundary. Otherwise, the selection will be adjusted
* to keep single character selected.
- * @param previousSelection previous selection result
+ * @param previousSelection previous selected text range.
* @param isStartHandle true if the start handle is being dragged
* @param lastOffset last offset of the text. It's actually the length of the text.
+ * @param handlesCrossed true if the selection handles are crossed
*
* @return the final startOffset, endOffset of the selection, and if the start and end are
* crossed each other.
*/
-private fun processAsSingleComposable(
+internal fun processAsSingleComposable(
rawStartOffset: Int,
rawEndOffset: Int,
- previousSelection: Selection?,
+ previousSelection: TextRange?,
isStartHandle: Boolean,
- lastOffset: Int
+ lastOffset: Int,
+ handlesCrossed: Boolean
): Triple<Int, Int, Boolean> {
var startOffset = rawStartOffset
var endOffset = rawEndOffset
if (startOffset == endOffset) {
+
+ // If the start and end offset are at the same character, and it's not the initial
+ // selection, then bound to at least one character.
val textRange = ensureAtLeastOneChar(
offset = rawStartOffset,
lastOffset = lastOffset,
previousSelection = previousSelection,
- isStartHandle = isStartHandle
+ isStartHandle = isStartHandle,
+ handlesCrossed = handlesCrossed
)
startOffset = textRange.start
endOffset = textRange.end
@@ -363,7 +89,7 @@
* @return the final startOffset, endOffset of the selection, and if the start and end handles are
* crossed each other.
*/
-private fun processCrossComposable(
+internal fun processCrossComposable(
startPosition: Offset,
endPosition: Offset,
rawStartOffset: Int,
@@ -414,7 +140,7 @@
*
* @return the adjusted word-based start and end offset of the selection.
*/
-private fun updateWordBasedSelection(
+internal fun updateWordBasedSelection(
textLayoutResult: TextLayoutResult,
startOffset: Int,
endOffset: Int,
@@ -442,33 +168,33 @@
* @param offset unprocessed start and end offset calculated directly from input position, in
* this case start and offset equals to each other.
* @param lastOffset last offset of the text. It's actually the length of the text.
- * @param previousSelection previous selection result
+ * @param previousSelection previous selected text range.
* @param isStartHandle true if the start handle is being dragged
+ * @param handlesCrossed true if the selection handles are crossed
*
* @return the adjusted [TextRange].
*/
private fun ensureAtLeastOneChar(
offset: Int,
lastOffset: Int,
- previousSelection: Selection?,
- isStartHandle: Boolean
+ previousSelection: TextRange?,
+ isStartHandle: Boolean,
+ handlesCrossed: Boolean
): TextRange {
var newStartOffset = offset
var newEndOffset = offset
- // If the start and end offset are at the same character, and it's not the
- // initial selection, then bound to at least one character.
previousSelection?.let {
if (isStartHandle) {
newStartOffset =
- if (it.handlesCrossed) {
- if (newEndOffset == 0 || it.start.offset == newEndOffset + 1) {
+ if (handlesCrossed) {
+ if (newEndOffset == 0 || it.start == newEndOffset + 1) {
newEndOffset + 1
} else {
newEndOffset - 1
}
} else {
- if (newEndOffset == lastOffset || it.start.offset == newEndOffset - 1) {
+ if (newEndOffset == lastOffset || it.start == newEndOffset - 1) {
newEndOffset - 1
} else {
newEndOffset + 1
@@ -476,14 +202,16 @@
}
} else {
newEndOffset =
- if (it.handlesCrossed) {
- if (newStartOffset == lastOffset || it.end.offset == newStartOffset - 1) {
+ if (handlesCrossed) {
+ if (
+ newStartOffset == lastOffset || it.end == newStartOffset - 1
+ ) {
newStartOffset - 1
} else {
newStartOffset + 1
}
} else {
- if (newStartOffset == 0 || it.end.offset == newStartOffset + 1) {
+ if (newStartOffset == 0 || it.end == newStartOffset + 1) {
newStartOffset + 1
} else {
newStartOffset - 1
@@ -505,7 +233,7 @@
*
* @return the graphical position where the selection handle should be.
*/
-private fun getSelectionHandleCoordinates(
+internal fun getSelectionHandleCoordinates(
textLayoutResult: TextLayoutResult,
offset: Int,
isStart: Boolean,
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/selection/TextFieldSelectionManagerTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/selection/TextFieldSelectionManagerTest.kt
new file mode 100644
index 0000000..c385596
--- /dev/null
+++ b/ui/ui-text/src/test/java/androidx/ui/text/selection/TextFieldSelectionManagerTest.kt
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.text.selection
+
+import androidx.test.filters.SmallTest
+import androidx.ui.core.Constraints
+import androidx.ui.core.LayoutDirection
+import androidx.ui.core.clipboard.ClipboardManager
+import androidx.ui.core.hapticfeedback.HapticFeedback
+import androidx.ui.core.hapticfeedback.HapticFeedbackType
+import androidx.ui.geometry.Offset
+import androidx.ui.input.OffsetMap
+import androidx.ui.input.TextFieldValue
+import androidx.ui.text.AnnotatedString
+import androidx.ui.text.TextFieldState
+import androidx.ui.text.TextLayoutInput
+import androidx.ui.text.TextRange
+import androidx.ui.text.TextStyle
+import androidx.ui.text.style.TextDirection
+import androidx.ui.text.style.TextOverflow
+import androidx.ui.unit.Density
+import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.spy
+import com.nhaarman.mockitokotlin2.times
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.whenever
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class TextFieldSelectionManagerTest {
+ private val text = "Hello World"
+ private val density = Density(density = 1f)
+ private val offsetMap = OffsetMap.identityOffsetMap
+ private var value = TextFieldValue(text)
+ private val lambda: (TextFieldValue) -> Unit = { value = it }
+ private val spyLambda = spy(lambda)
+ private val state = TextFieldState(mock())
+
+ private val dragBeginPosition = Offset.Zero
+ private val dragDistance = Offset(300f, 15f)
+ private val beginOffset = 0
+ private val dragOffset = text.indexOf('W')
+ private val longPressTextRange = TextRange(0, "Hello".length)
+ private val dragTextRange = TextRange("Hello".length + 1, text.length)
+
+ private val manager = TextFieldSelectionManager()
+
+ private val clipboardManager = mock<ClipboardManager>()
+ private val hapticFeedback = mock<HapticFeedback>()
+
+ @Before
+ fun setup() {
+ manager.offsetMap = offsetMap
+ manager.onValueChange = lambda
+ manager.state = state
+ manager.value = value
+ manager.clipboardManager = clipboardManager
+ manager.hapticFeedBack = hapticFeedback
+
+ state.layoutResult = mock()
+ whenever(state.layoutResult!!.layoutInput).thenReturn(
+ TextLayoutInput(
+ text = AnnotatedString(text),
+ style = TextStyle.Default,
+ placeholders = mock(),
+ maxLines = 2,
+ softWrap = true,
+ overflow = TextOverflow.Ellipsis,
+ density = density,
+ layoutDirection = LayoutDirection.Ltr,
+ resourceLoader = mock(),
+ constraints = Constraints()
+ )
+ )
+ whenever(state.layoutResult!!.getOffsetForPosition(dragBeginPosition)).thenReturn(
+ beginOffset
+ )
+ whenever(state.layoutResult!!.getOffsetForPosition(dragDistance)).thenReturn(dragOffset)
+ whenever(state.layoutResult!!.getWordBoundary(beginOffset)).thenReturn(longPressTextRange)
+ whenever(state.layoutResult!!.getWordBoundary(dragOffset)).thenReturn(dragTextRange)
+ whenever(state.layoutResult!!.getBidiRunDirection(any())).thenReturn(TextDirection.Ltr)
+ }
+
+ @Test
+ fun TextFieldSelectionManager_init() {
+ assertThat(manager.offsetMap).isEqualTo(offsetMap)
+ assertThat(manager.onValueChange).isEqualTo(lambda)
+ assertThat(manager.state).isEqualTo(state)
+ assertThat(manager.value).isEqualTo(value)
+ }
+
+ @Test
+ fun TextFieldSelectionManager_longPressDragObserver_onLongPress() {
+ manager.longPressDragObserver.onLongPress(dragBeginPosition)
+
+ assertThat(state.selectionIsOn).isTrue()
+ assertThat(value.selection).isEqualTo(longPressTextRange)
+ verify(
+ hapticFeedback,
+ times(1)
+ ).performHapticFeedback(HapticFeedbackType.TextHandleMove)
+ }
+
+ @Test
+ fun TextFieldSelectionManager_longPressDragObserver_onDrag() {
+ manager.longPressDragObserver.onLongPress(dragBeginPosition)
+ manager.longPressDragObserver.onDrag(dragDistance)
+
+ assertThat(value.selection).isEqualTo(TextRange(0, text.length))
+ verify(
+ hapticFeedback,
+ times(2)
+ ).performHapticFeedback(HapticFeedbackType.TextHandleMove)
+ }
+
+ @Test
+ fun copy_selection_collapse() {
+ manager.value = TextFieldValue(text = text, selection = TextRange(4, 4))
+
+ manager.copy()
+
+ verify(clipboardManager, times(0)).setText(any())
+ }
+
+ @Test
+ fun copy_selection_not_null() {
+ manager.value = TextFieldValue(text = text, selection = TextRange(0, "Hello".length))
+
+ manager.copy()
+
+ verify(clipboardManager, times(1)).setText(AnnotatedString("Hello"))
+ assertThat(value.selection).isEqualTo(TextRange("Hello".length, "Hello".length))
+ assertThat(state.selectionIsOn).isFalse()
+ }
+
+ @Test
+ fun paste_clipBoardManager_null() {
+ manager.clipboardManager = null
+
+ manager.paste()
+
+ verify(spyLambda, times(0)).invoke(any())
+ }
+
+ @Test
+ fun paste_clipBoardManager_empty() {
+ whenever(clipboardManager.getText()).thenReturn(null)
+
+ manager.paste()
+
+ verify(spyLambda, times(0)).invoke(any())
+ }
+
+ @Test
+ fun paste_clipBoardManager_not_empty() {
+ whenever(clipboardManager.getText()).thenReturn(AnnotatedString("Hello"))
+ manager.value = TextFieldValue(
+ text = text,
+ selection = TextRange("Hel".length, "Hello Wo".length)
+ )
+
+ manager.paste()
+
+ assertThat(value.text).isEqualTo("HelHellorld")
+ assertThat(value.selection).isEqualTo(TextRange("Hello Wo".length, "Hello Wo".length))
+ assertThat(state.selectionIsOn).isFalse()
+ }
+
+ @Test
+ fun cut_selection_collapse() {
+ manager.value = TextFieldValue(text = text, selection = TextRange(4, 4))
+
+ manager.cut()
+
+ verify(clipboardManager, times(0)).setText(any())
+ }
+
+ @Test
+ fun cut_selection_not_null() {
+ manager.value = TextFieldValue(
+ text = text + text,
+ selection = TextRange("Hello".length, text.length))
+
+ manager.cut()
+
+ verify(clipboardManager, times(1)).setText(AnnotatedString(" World"))
+ assertThat(value.text).isEqualTo("HelloHello World")
+ assertThat(value.selection).isEqualTo(TextRange("Hello".length, "Hello".length))
+ assertThat(state.selectionIsOn).isFalse()
+ }
+}
diff --git a/ui/ui-tooling/OWNERS b/ui/ui-tooling/OWNERS
index 583d415..36d6fce 100644
--- a/ui/ui-tooling/OWNERS
+++ b/ui/ui-tooling/OWNERS
@@ -1,3 +1,4 @@
[email protected]
[email protected]
[email protected]
\ No newline at end of file
[email protected]
[email protected]
\ No newline at end of file
diff --git a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/animation/PreviewAnimationClockTest.kt b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
similarity index 94%
rename from ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/animation/PreviewAnimationClockTest.kt
rename to ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
index ca6a8ce..e6dbd0a 100644
--- a/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/animation/PreviewAnimationClockTest.kt
+++ b/ui/ui-tooling/src/androidTest/java/androidx/ui/tooling/preview/animation/PreviewAnimationClockTest.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package androidx.ui.tooling.animation
+package androidx.ui.tooling.preview.animation
import androidx.animation.AnimationClockObserver
-import androidx.ui.tooling.preview.animation.PreviewAnimationClock
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
diff --git a/ui/ui-unit/api/0.1.0-dev15.txt b/ui/ui-unit/api/0.1.0-dev15.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/0.1.0-dev15.txt
+++ b/ui/ui-unit/api/0.1.0-dev15.txt
@@ -17,7 +17,7 @@
property public final int maxWidth;
property public final int minHeight;
property public final int minWidth;
- field public static final androidx.ui.core.Constraints.Companion! Companion;
+ field public static final androidx.ui.core.Constraints.Companion Companion;
field public static final int Infinity = 2147483647; // 0x7fffffff
}
@@ -41,6 +41,8 @@
}
public enum LayoutDirection {
+ method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutDirection[] values();
enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
}
@@ -108,7 +110,7 @@
method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float other);
method @androidx.compose.Stable public static String toString-impl(float $this);
method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
- field public static final androidx.ui.unit.Dp.Companion! Companion;
+ field public static final androidx.ui.unit.Dp.Companion Companion;
}
public static final class Dp.Companion {
@@ -214,7 +216,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
- field public static final androidx.ui.unit.Duration.Companion! Companion;
+ field public static final androidx.ui.unit.Duration.Companion Companion;
}
public static final class Duration.Companion {
@@ -268,7 +270,7 @@
method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
property public final int x;
property public final int y;
- field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+ field public static final androidx.ui.unit.IntOffset.Companion Companion;
}
public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
property public final int height;
property public final int width;
- field public static final androidx.ui.unit.IntSize.Companion! Companion;
+ field public static final androidx.ui.unit.IntSize.Companion Companion;
}
public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
method public static inline operator long times-impl(long $this, int other);
method public static String toString-impl(long $this);
method public static inline operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+ field public static final androidx.ui.unit.TextUnit.Companion Companion;
}
public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
}
public enum TextUnitType {
+ method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.unit.TextUnitType[] values();
enum_constant public static final androidx.ui.unit.TextUnitType Em;
enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
- field public static final androidx.ui.unit.Uptime.Companion! Companion;
+ field public static final androidx.ui.unit.Uptime.Companion Companion;
}
public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
method public androidx.ui.geometry.Offset getPixelsPerSecond();
method public operator androidx.ui.unit.Velocity unaryMinus();
- field public static final androidx.ui.unit.Velocity.Companion! Companion;
+ field public static final androidx.ui.unit.Velocity.Companion Companion;
}
public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/api_lint.ignore b/ui/ui-unit/api/api_lint.ignore
index aad744b..319f1ff 100644
--- a/ui/ui-unit/api/api_lint.ignore
+++ b/ui/ui-unit/api/api_lint.ignore
@@ -1,7 +1,3 @@
// Baseline format: 1.0
MethodNameUnits: androidx.ui.unit.Durations#inSeconds(androidx.ui.unit.Duration):
Returned time values must be in milliseconds, was `inSeconds`
-
-
-MissingNullability: androidx.ui.core.Constraints2#toString-impl(long):
- Missing nullability on method `toString-impl` return
diff --git a/ui/ui-unit/api/current.txt b/ui/ui-unit/api/current.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/current.txt
+++ b/ui/ui-unit/api/current.txt
@@ -17,7 +17,7 @@
property public final int maxWidth;
property public final int minHeight;
property public final int minWidth;
- field public static final androidx.ui.core.Constraints.Companion! Companion;
+ field public static final androidx.ui.core.Constraints.Companion Companion;
field public static final int Infinity = 2147483647; // 0x7fffffff
}
@@ -41,6 +41,8 @@
}
public enum LayoutDirection {
+ method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutDirection[] values();
enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
}
@@ -108,7 +110,7 @@
method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float other);
method @androidx.compose.Stable public static String toString-impl(float $this);
method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
- field public static final androidx.ui.unit.Dp.Companion! Companion;
+ field public static final androidx.ui.unit.Dp.Companion Companion;
}
public static final class Dp.Companion {
@@ -214,7 +216,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
- field public static final androidx.ui.unit.Duration.Companion! Companion;
+ field public static final androidx.ui.unit.Duration.Companion Companion;
}
public static final class Duration.Companion {
@@ -268,7 +270,7 @@
method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
property public final int x;
property public final int y;
- field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+ field public static final androidx.ui.unit.IntOffset.Companion Companion;
}
public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
property public final int height;
property public final int width;
- field public static final androidx.ui.unit.IntSize.Companion! Companion;
+ field public static final androidx.ui.unit.IntSize.Companion Companion;
}
public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
method public static inline operator long times-impl(long $this, int other);
method public static String toString-impl(long $this);
method public static inline operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+ field public static final androidx.ui.unit.TextUnit.Companion Companion;
}
public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
}
public enum TextUnitType {
+ method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.unit.TextUnitType[] values();
enum_constant public static final androidx.ui.unit.TextUnitType Em;
enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
- field public static final androidx.ui.unit.Uptime.Companion! Companion;
+ field public static final androidx.ui.unit.Uptime.Companion Companion;
}
public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
method public androidx.ui.geometry.Offset getPixelsPerSecond();
method public operator androidx.ui.unit.Velocity unaryMinus();
- field public static final androidx.ui.unit.Velocity.Companion! Companion;
+ field public static final androidx.ui.unit.Velocity.Companion Companion;
}
public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt
+++ b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
property public final int maxWidth;
property public final int minHeight;
property public final int minWidth;
- field public static final androidx.ui.core.Constraints.Companion! Companion;
+ field public static final androidx.ui.core.Constraints.Companion Companion;
field public static final int Infinity = 2147483647; // 0x7fffffff
}
@@ -41,6 +41,8 @@
}
public enum LayoutDirection {
+ method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutDirection[] values();
enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
}
@@ -108,7 +110,7 @@
method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float other);
method @androidx.compose.Stable public static String toString-impl(float $this);
method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
- field public static final androidx.ui.unit.Dp.Companion! Companion;
+ field public static final androidx.ui.unit.Dp.Companion Companion;
}
public static final class Dp.Companion {
@@ -214,7 +216,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
- field public static final androidx.ui.unit.Duration.Companion! Companion;
+ field public static final androidx.ui.unit.Duration.Companion Companion;
}
public static final class Duration.Companion {
@@ -268,7 +270,7 @@
method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
property public final int x;
property public final int y;
- field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+ field public static final androidx.ui.unit.IntOffset.Companion Companion;
}
public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
property public final int height;
property public final int width;
- field public static final androidx.ui.unit.IntSize.Companion! Companion;
+ field public static final androidx.ui.unit.IntSize.Companion Companion;
}
public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
method public static inline operator long times-impl(long $this, int other);
method public static String toString-impl(long $this);
method public static inline operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+ field public static final androidx.ui.unit.TextUnit.Companion Companion;
}
public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
}
public enum TextUnitType {
+ method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.unit.TextUnitType[] values();
enum_constant public static final androidx.ui.unit.TextUnitType Em;
enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
- field public static final androidx.ui.unit.Uptime.Companion! Companion;
+ field public static final androidx.ui.unit.Uptime.Companion Companion;
}
public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
method public androidx.ui.geometry.Offset getPixelsPerSecond();
method public operator androidx.ui.unit.Velocity unaryMinus();
- field public static final androidx.ui.unit.Velocity.Companion! Companion;
+ field public static final androidx.ui.unit.Velocity.Companion Companion;
}
public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/public_plus_experimental_current.txt b/ui/ui-unit/api/public_plus_experimental_current.txt
index 08c7a60..1f0e0c3 100644
--- a/ui/ui-unit/api/public_plus_experimental_current.txt
+++ b/ui/ui-unit/api/public_plus_experimental_current.txt
@@ -17,7 +17,7 @@
property public final int maxWidth;
property public final int minHeight;
property public final int minWidth;
- field public static final androidx.ui.core.Constraints.Companion! Companion;
+ field public static final androidx.ui.core.Constraints.Companion Companion;
field public static final int Infinity = 2147483647; // 0x7fffffff
}
@@ -41,6 +41,8 @@
}
public enum LayoutDirection {
+ method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutDirection[] values();
enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
}
@@ -108,7 +110,7 @@
method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float other);
method @androidx.compose.Stable public static String toString-impl(float $this);
method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
- field public static final androidx.ui.unit.Dp.Companion! Companion;
+ field public static final androidx.ui.unit.Dp.Companion Companion;
}
public static final class Dp.Companion {
@@ -214,7 +216,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
- field public static final androidx.ui.unit.Duration.Companion! Companion;
+ field public static final androidx.ui.unit.Duration.Companion Companion;
}
public static final class Duration.Companion {
@@ -268,7 +270,7 @@
method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
property public final int x;
property public final int y;
- field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+ field public static final androidx.ui.unit.IntOffset.Companion Companion;
}
public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
property public final int height;
property public final int width;
- field public static final androidx.ui.unit.IntSize.Companion! Companion;
+ field public static final androidx.ui.unit.IntSize.Companion Companion;
}
public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
method public static inline operator long times-impl(long $this, int other);
method public static String toString-impl(long $this);
method public static inline operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+ field public static final androidx.ui.unit.TextUnit.Companion Companion;
}
public static final class TextUnit.Companion {
@@ -458,6 +460,8 @@
}
public enum TextUnitType {
+ method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.unit.TextUnitType[] values();
enum_constant public static final androidx.ui.unit.TextUnitType Em;
enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -472,7 +476,7 @@
method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
- field public static final androidx.ui.unit.Uptime.Companion! Companion;
+ field public static final androidx.ui.unit.Uptime.Companion Companion;
}
public static final class Uptime.Companion {
@@ -490,7 +494,7 @@
method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
method public androidx.ui.geometry.Offset getPixelsPerSecond();
method public operator androidx.ui.unit.Velocity unaryMinus();
- field public static final androidx.ui.unit.Velocity.Companion! Companion;
+ field public static final androidx.ui.unit.Velocity.Companion Companion;
}
public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/restricted_0.1.0-dev15.txt b/ui/ui-unit/api/restricted_0.1.0-dev15.txt
index 82aef00..29c348b 100644
--- a/ui/ui-unit/api/restricted_0.1.0-dev15.txt
+++ b/ui/ui-unit/api/restricted_0.1.0-dev15.txt
@@ -17,7 +17,7 @@
property public final int maxWidth;
property public final int minHeight;
property public final int minWidth;
- field public static final androidx.ui.core.Constraints.Companion! Companion;
+ field public static final androidx.ui.core.Constraints.Companion Companion;
field public static final int Infinity = 2147483647; // 0x7fffffff
}
@@ -41,6 +41,8 @@
}
public enum LayoutDirection {
+ method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutDirection[] values();
enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
}
@@ -108,7 +110,7 @@
method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float other);
method @androidx.compose.Stable public static String toString-impl(float $this);
method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
- field public static final androidx.ui.unit.Dp.Companion! Companion;
+ field public static final androidx.ui.unit.Dp.Companion Companion;
}
public static final class Dp.Companion {
@@ -214,7 +216,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
- field public static final androidx.ui.unit.Duration.Companion! Companion;
+ field public static final androidx.ui.unit.Duration.Companion Companion;
}
public static final class Duration.Companion {
@@ -268,7 +270,7 @@
method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
property public final int x;
property public final int y;
- field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+ field public static final androidx.ui.unit.IntOffset.Companion Companion;
}
public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
property public final int height;
property public final int width;
- field public static final androidx.ui.unit.IntSize.Companion! Companion;
+ field public static final androidx.ui.unit.IntSize.Companion Companion;
}
public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
method public static inline operator long times-impl(long $this, int other);
method public static String toString-impl(long $this);
method public static inline operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+ field public static final androidx.ui.unit.TextUnit.Companion Companion;
}
public static final class TextUnit.Companion {
@@ -462,6 +464,8 @@
}
public enum TextUnitType {
+ method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.unit.TextUnitType[] values();
enum_constant public static final androidx.ui.unit.TextUnitType Em;
enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -476,7 +480,7 @@
method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
- field public static final androidx.ui.unit.Uptime.Companion! Companion;
+ field public static final androidx.ui.unit.Uptime.Companion Companion;
}
public static final class Uptime.Companion {
@@ -494,7 +498,7 @@
method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
method public androidx.ui.geometry.Offset getPixelsPerSecond();
method public operator androidx.ui.unit.Velocity unaryMinus();
- field public static final androidx.ui.unit.Velocity.Companion! Companion;
+ field public static final androidx.ui.unit.Velocity.Companion Companion;
}
public static final class Velocity.Companion {
diff --git a/ui/ui-unit/api/restricted_current.txt b/ui/ui-unit/api/restricted_current.txt
index 82aef00..29c348b 100644
--- a/ui/ui-unit/api/restricted_current.txt
+++ b/ui/ui-unit/api/restricted_current.txt
@@ -17,7 +17,7 @@
property public final int maxWidth;
property public final int minHeight;
property public final int minWidth;
- field public static final androidx.ui.core.Constraints.Companion! Companion;
+ field public static final androidx.ui.core.Constraints.Companion Companion;
field public static final int Infinity = 2147483647; // 0x7fffffff
}
@@ -41,6 +41,8 @@
}
public enum LayoutDirection {
+ method public static androidx.ui.core.LayoutDirection valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.core.LayoutDirection[] values();
enum_constant public static final androidx.ui.core.LayoutDirection Ltr;
enum_constant public static final androidx.ui.core.LayoutDirection Rtl;
}
@@ -108,7 +110,7 @@
method @androidx.compose.Stable public static inline operator float times-x8crYZs(float $this, float other);
method @androidx.compose.Stable public static String toString-impl(float $this);
method @androidx.compose.Stable public static inline operator float unaryMinus-impl(float $this);
- field public static final androidx.ui.unit.Dp.Companion! Companion;
+ field public static final androidx.ui.unit.Dp.Companion Companion;
}
public static final class Dp.Companion {
@@ -214,7 +216,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.Duration plus(androidx.ui.unit.Duration other);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(int factor);
method @androidx.compose.Stable public operator androidx.ui.unit.Duration times(double factor);
- field public static final androidx.ui.unit.Duration.Companion! Companion;
+ field public static final androidx.ui.unit.Duration.Companion Companion;
}
public static final class Duration.Companion {
@@ -268,7 +270,7 @@
method @androidx.compose.Stable public inline operator androidx.ui.unit.IntOffset unaryMinus();
property public final int x;
property public final int y;
- field public static final androidx.ui.unit.IntOffset.Companion! Companion;
+ field public static final androidx.ui.unit.IntOffset.Companion Companion;
}
public static final class IntOffset.Companion {
@@ -296,7 +298,7 @@
method @androidx.compose.Stable public operator androidx.ui.unit.IntSize times(int other);
property public final int height;
property public final int width;
- field public static final androidx.ui.unit.IntSize.Companion! Companion;
+ field public static final androidx.ui.unit.IntSize.Companion Companion;
}
public static final class IntSize.Companion {
@@ -425,7 +427,7 @@
method public static inline operator long times-impl(long $this, int other);
method public static String toString-impl(long $this);
method public static inline operator long unaryMinus-impl(long $this);
- field public static final androidx.ui.unit.TextUnit.Companion! Companion;
+ field public static final androidx.ui.unit.TextUnit.Companion Companion;
}
public static final class TextUnit.Companion {
@@ -462,6 +464,8 @@
}
public enum TextUnitType {
+ method public static androidx.ui.unit.TextUnitType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static androidx.ui.unit.TextUnitType[] values();
enum_constant public static final androidx.ui.unit.TextUnitType Em;
enum_constant public static final androidx.ui.unit.TextUnitType Inherit;
enum_constant public static final androidx.ui.unit.TextUnitType Sp;
@@ -476,7 +480,7 @@
method public operator androidx.ui.unit.Uptime minus(androidx.ui.unit.Duration duration);
method public operator androidx.ui.unit.Duration minus(androidx.ui.unit.Uptime other);
method public operator androidx.ui.unit.Uptime plus(androidx.ui.unit.Duration duration);
- field public static final androidx.ui.unit.Uptime.Companion! Companion;
+ field public static final androidx.ui.unit.Uptime.Companion Companion;
}
public static final class Uptime.Companion {
@@ -494,7 +498,7 @@
method @androidx.compose.Immutable public androidx.ui.unit.Velocity copy(androidx.ui.geometry.Offset pixelsPerSecond);
method public androidx.ui.geometry.Offset getPixelsPerSecond();
method public operator androidx.ui.unit.Velocity unaryMinus();
- field public static final androidx.ui.unit.Velocity.Companion! Companion;
+ field public static final androidx.ui.unit.Velocity.Companion Companion;
}
public static final class Velocity.Companion {
diff --git a/vectordrawable/vectordrawable-animated/api/api_lint.ignore b/vectordrawable/vectordrawable-animated/api/api_lint.ignore
index 8bbfad4..ffd0fdf 100644
--- a/vectordrawable/vectordrawable-animated/api/api_lint.ignore
+++ b/vectordrawable/vectordrawable-animated/api/api_lint.ignore
@@ -59,7 +59,3 @@
Missing nullability on parameter `dr` in method `unregisterAnimationCallback`
MissingNullability: androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat#unregisterAnimationCallback(android.graphics.drawable.Drawable, androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback) parameter #1:
Missing nullability on parameter `callback` in method `unregisterAnimationCallback`
-
-
-NotCloseable: androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat:
- Classes that release resources (stop()) should implement AutoClosable and CloseGuard: class androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
diff --git a/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml b/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml
index 9ad6fef..f48b579 100644
--- a/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml
+++ b/work/workmanager-benchmark/src/androidTest/AndroidManifest.xml
@@ -22,5 +22,8 @@
<application
android:debuggable="false"
tools:replace="android:debuggable">
+ <!-- enable profileableByShell for non-intrusive profiling tools -->
+ <!--suppress AndroidElementNotAllowed -->
+ <profileable android:shell="true"/>
</application>
</manifest>
diff --git a/work/workmanager/api/2.4.0-rc01.txt b/work/workmanager/api/2.4.0-rc01.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/2.4.0-rc01.txt
+++ b/work/workmanager/api/2.4.0-rc01.txt
@@ -46,7 +46,7 @@
method public boolean requiresCharging();
method @RequiresApi(23) public boolean requiresDeviceIdle();
method public boolean requiresStorageNotLow();
- field public static final androidx.work.Constraints! NONE;
+ field public static final androidx.work.Constraints NONE;
}
public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
method public String![]? getStringArray(String);
method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
method public byte[] toByteArray();
- field public static final androidx.work.Data! EMPTY;
+ field public static final androidx.work.Data EMPTY;
field public static final int MAX_DATA_BYTES = 10240; // 0x2800
}
diff --git a/work/workmanager/api/api_lint.ignore b/work/workmanager/api/api_lint.ignore
index 444e9d1..8454552 100644
--- a/work/workmanager/api/api_lint.ignore
+++ b/work/workmanager/api/api_lint.ignore
@@ -45,14 +45,10 @@
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.work.WorkRequest.Builder.keepResultsForAtLeast(long,java.util.concurrent.TimeUnit)
-MissingNullability: androidx.work.Constraints#NONE:
- Missing nullability on field `NONE` in class `class androidx.work.Constraints`
MissingNullability: androidx.work.Constraints.Builder#setTriggerContentMaxDelay(java.time.Duration) parameter #0:
Missing nullability on parameter `duration` in method `setTriggerContentMaxDelay`
MissingNullability: androidx.work.Constraints.Builder#setTriggerContentUpdateDelay(java.time.Duration) parameter #0:
Missing nullability on parameter `duration` in method `setTriggerContentUpdateDelay`
-MissingNullability: androidx.work.Data#EMPTY:
- Missing nullability on field `EMPTY` in class `class androidx.work.Data`
NoByteOrShort: androidx.work.Data#getByte(String, byte):
@@ -61,19 +57,3 @@
Should avoid odd sized primitives; use `int` instead of `byte` in parameter defaultValue in androidx.work.Data.getByte(String key, byte defaultValue)
NoByteOrShort: androidx.work.Data.Builder#putByte(String, byte) parameter #1:
Should avoid odd sized primitives; use `int` instead of `byte` in parameter value in androidx.work.Data.Builder.putByte(String key, byte value)
-
-
-SetterReturnsThis: androidx.work.WorkRequest.Builder#addTag(String):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.addTag(String)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setBackoffCriteria(androidx.work.BackoffPolicy, java.time.Duration):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setBackoffCriteria(androidx.work.BackoffPolicy,java.time.Duration)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setBackoffCriteria(androidx.work.BackoffPolicy, long, java.util.concurrent.TimeUnit):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setBackoffCriteria(androidx.work.BackoffPolicy,long,java.util.concurrent.TimeUnit)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setConstraints(androidx.work.Constraints):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setConstraints(androidx.work.Constraints)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setInitialDelay(java.time.Duration):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setInitialDelay(java.time.Duration)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setInitialDelay(long, java.util.concurrent.TimeUnit):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setInitialDelay(long,java.util.concurrent.TimeUnit)
-SetterReturnsThis: androidx.work.WorkRequest.Builder#setInputData(androidx.work.Data):
- Methods must return the builder object (return type androidx.work.WorkRequest.Builder<B,W> instead of B): method androidx.work.WorkRequest.Builder.setInputData(androidx.work.Data)
diff --git a/work/workmanager/api/current.txt b/work/workmanager/api/current.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/current.txt
+++ b/work/workmanager/api/current.txt
@@ -46,7 +46,7 @@
method public boolean requiresCharging();
method @RequiresApi(23) public boolean requiresDeviceIdle();
method public boolean requiresStorageNotLow();
- field public static final androidx.work.Constraints! NONE;
+ field public static final androidx.work.Constraints NONE;
}
public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
method public String![]? getStringArray(String);
method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
method public byte[] toByteArray();
- field public static final androidx.work.Data! EMPTY;
+ field public static final androidx.work.Data EMPTY;
field public static final int MAX_DATA_BYTES = 10240; // 0x2800
}
diff --git a/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt b/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt
+++ b/work/workmanager/api/public_plus_experimental_2.4.0-rc01.txt
@@ -46,7 +46,7 @@
method public boolean requiresCharging();
method @RequiresApi(23) public boolean requiresDeviceIdle();
method public boolean requiresStorageNotLow();
- field public static final androidx.work.Constraints! NONE;
+ field public static final androidx.work.Constraints NONE;
}
public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
method public String![]? getStringArray(String);
method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
method public byte[] toByteArray();
- field public static final androidx.work.Data! EMPTY;
+ field public static final androidx.work.Data EMPTY;
field public static final int MAX_DATA_BYTES = 10240; // 0x2800
}
diff --git a/work/workmanager/api/public_plus_experimental_current.txt b/work/workmanager/api/public_plus_experimental_current.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/public_plus_experimental_current.txt
+++ b/work/workmanager/api/public_plus_experimental_current.txt
@@ -46,7 +46,7 @@
method public boolean requiresCharging();
method @RequiresApi(23) public boolean requiresDeviceIdle();
method public boolean requiresStorageNotLow();
- field public static final androidx.work.Constraints! NONE;
+ field public static final androidx.work.Constraints NONE;
}
public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
method public String![]? getStringArray(String);
method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
method public byte[] toByteArray();
- field public static final androidx.work.Data! EMPTY;
+ field public static final androidx.work.Data EMPTY;
field public static final int MAX_DATA_BYTES = 10240; // 0x2800
}
diff --git a/work/workmanager/api/restricted_2.4.0-rc01.txt b/work/workmanager/api/restricted_2.4.0-rc01.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/restricted_2.4.0-rc01.txt
+++ b/work/workmanager/api/restricted_2.4.0-rc01.txt
@@ -46,7 +46,7 @@
method public boolean requiresCharging();
method @RequiresApi(23) public boolean requiresDeviceIdle();
method public boolean requiresStorageNotLow();
- field public static final androidx.work.Constraints! NONE;
+ field public static final androidx.work.Constraints NONE;
}
public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
method public String![]? getStringArray(String);
method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
method public byte[] toByteArray();
- field public static final androidx.work.Data! EMPTY;
+ field public static final androidx.work.Data EMPTY;
field public static final int MAX_DATA_BYTES = 10240; // 0x2800
}
diff --git a/work/workmanager/api/restricted_current.txt b/work/workmanager/api/restricted_current.txt
index 25adbb9..6c0ce36 100644
--- a/work/workmanager/api/restricted_current.txt
+++ b/work/workmanager/api/restricted_current.txt
@@ -46,7 +46,7 @@
method public boolean requiresCharging();
method @RequiresApi(23) public boolean requiresDeviceIdle();
method public boolean requiresStorageNotLow();
- field public static final androidx.work.Constraints! NONE;
+ field public static final androidx.work.Constraints NONE;
}
public static final class Constraints.Builder {
@@ -84,7 +84,7 @@
method public String![]? getStringArray(String);
method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
method public byte[] toByteArray();
- field public static final androidx.work.Data! EMPTY;
+ field public static final androidx.work.Data EMPTY;
field public static final int MAX_DATA_BYTES = 10240; // 0x2800
}
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
index 54ba57a..8f84b5b 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/systemalarm/RescheduleReceiver.java
@@ -43,7 +43,7 @@
// WorkManager has not already been initialized.
Logger.get().error(TAG,
"Cannot reschedule jobs. WorkManager needs to be initialized via a "
- + "ContentProvider#onCreate() or an Application#onCreate().");
+ + "ContentProvider#onCreate() or an Application#onCreate().", e);
}
} else {
Intent reschedule = CommandHandler.createRescheduleIntent(context);