302 lines
10 KiB
Kotlin
302 lines
10 KiB
Kotlin
/*
|
|
* Copyright 2016 JetBrains s.r.o.
|
|
*
|
|
* 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("unused")
|
|
|
|
package org.jetbrains.anko
|
|
|
|
import android.app.Activity
|
|
import android.content.Context
|
|
import android.os.Build
|
|
import androidx.annotation.ChecksSdkIntAtLeast
|
|
import androidx.fragment.app.Fragment
|
|
import org.jetbrains.anko.internals.AnkoInternals
|
|
|
|
open class AnkoException(message: String = "") : RuntimeException(message)
|
|
|
|
/**
|
|
* Return the grayscale color with the zero opacity using the single color value.
|
|
* E.g., 0xC0 will be translated to 0xC0C0C0.
|
|
*/
|
|
val Int.gray: Int
|
|
get() = this or (this shl 8) or (this shl 16)
|
|
|
|
/**
|
|
* Return the color with 0xFF opacity.
|
|
* E.g., 0xabcdef will be translated to 0xFFabcdef.
|
|
*/
|
|
val Int.opaque: Int
|
|
get() = this or 0xff000000.toInt()
|
|
|
|
/**
|
|
* Return the color with the given alpha value.
|
|
* Examples:
|
|
* 0xabcdef.withAlpha(0xCF) == 0xCFabcdef
|
|
* 0xFFabcdef.withAlpha(0xCF) == 0xCFabcdef
|
|
*
|
|
* @param alpha the alpha channel value: [0x0..0xFF].
|
|
* @return the color with the given alpha value applied.
|
|
*/
|
|
fun Int.withAlpha(alpha: Int): Int {
|
|
require(alpha in 0..0xFF)
|
|
return this and 0x00FFFFFF or (alpha shl 24)
|
|
}
|
|
|
|
enum class ScreenSize {
|
|
SMALL,
|
|
NORMAL,
|
|
LARGE,
|
|
XLARGE
|
|
}
|
|
|
|
enum class UiMode {
|
|
NORMAL,
|
|
CAR,
|
|
DESK,
|
|
TELEVISION,
|
|
APPLIANCE,
|
|
WATCH
|
|
}
|
|
|
|
enum class Orientation {
|
|
PORTRAIT,
|
|
LANDSCAPE,
|
|
SQUARE
|
|
}
|
|
|
|
/**
|
|
* Execute [f] if the device configuration matches all given constraints.
|
|
* You can use named arguments to provide only the relevant constraints.
|
|
* All null constraints are ignored.
|
|
*
|
|
* @param screenSize the required screen size.
|
|
* @param density the required screen density.
|
|
* @param language the required system language.
|
|
* @param orientation the current screen orientation.
|
|
* @param long true, if the screen layout is long. See Configuration.SCREENLAYOUT_LONG_YES for more information.
|
|
* @param fromSdk the minimal SDK version for code to execute.
|
|
* @param sdk the target SDK version. Code will not be executed if the device Android SDK version is different
|
|
* (lower or higher than the given value).
|
|
* @param uiMode the required interface mode.
|
|
* @param nightMode true, if the device should be in the night mode, false if should not.
|
|
* @param rightToLeft true, if the device locale should be a right-to-left one, false if should not.
|
|
* @param smallestWidth the required smallest width of the screen.
|
|
*/
|
|
inline fun <T : Any> Context.configuration(
|
|
screenSize: ScreenSize? = null,
|
|
density: ClosedRange<Int>? = null,
|
|
language: String? = null,
|
|
orientation: Orientation? = null,
|
|
long: Boolean? = null,
|
|
fromSdk: Int? = null,
|
|
sdk: Int? = null,
|
|
uiMode: UiMode? = null,
|
|
nightMode: Boolean? = null,
|
|
rightToLeft: Boolean? = null,
|
|
smallestWidth: Int? = null,
|
|
f: () -> T,
|
|
): T? = if (AnkoInternals.testConfiguration(
|
|
this, screenSize, density, language, orientation, long,
|
|
fromSdk, sdk, uiMode, nightMode, rightToLeft, smallestWidth
|
|
)
|
|
) f() else null
|
|
|
|
/**
|
|
* Execute [f] if the device configuration matches all given constraints.
|
|
* You can use named arguments to provide only the relevant constraints.
|
|
* All null constraints are ignored.
|
|
*
|
|
* @param screenSize the required screen size.
|
|
* @param density the required screen density.
|
|
* @param language the required system language.
|
|
* @param orientation the current screen orientation.
|
|
* @param long true, if the screen layout is long. See Configuration.SCREENLAYOUT_LONG_YES for more information.
|
|
* @param fromSdk the minimal SDK version for code to execute.
|
|
* @param sdk the target SDK version. Code will not be executed if the device Android SDK version is different
|
|
* (lower or higher than the given value).
|
|
* @param uiMode the required interface mode.
|
|
* @param nightMode true, if the device should be in the night mode, false if should not.
|
|
* @param rightToLeft true, if the device locale should be a right-to-left one, false if should not.
|
|
* @param smallestWidth the required smallest width of the screen.
|
|
*/
|
|
inline fun <T : Any> Activity.configuration(
|
|
screenSize: ScreenSize? = null,
|
|
density: ClosedRange<Int>? = null,
|
|
language: String? = null,
|
|
orientation: Orientation? = null,
|
|
long: Boolean? = null,
|
|
fromSdk: Int? = null,
|
|
sdk: Int? = null,
|
|
uiMode: UiMode? = null,
|
|
nightMode: Boolean? = null,
|
|
rightToLeft: Boolean? = null,
|
|
smallestWidth: Int? = null,
|
|
f: () -> T,
|
|
): T? = if (AnkoInternals.testConfiguration(
|
|
this, screenSize, density, language, orientation, long,
|
|
fromSdk, sdk, uiMode, nightMode, rightToLeft, smallestWidth
|
|
)
|
|
) f() else null
|
|
|
|
/**
|
|
* Execute [f] if the device configuration matches all given constraints.
|
|
* You can use named arguments to provide only the relevant constraints.
|
|
* All null constraints are ignored.
|
|
*
|
|
* @param screenSize the required screen size.
|
|
* @param density the required screen density.
|
|
* @param language the required system language.
|
|
* @param orientation the current screen orientation.
|
|
* @param long true, if the screen layout is long. See Configuration.SCREENLAYOUT_LONG_YES for more information.
|
|
* @param fromSdk the minimal SDK version for code to execute.
|
|
* @param sdk the target SDK version. Code will not be executed if the device Android SDK version is different
|
|
* (lower or higher than the given value).
|
|
* @param uiMode the required interface mode.
|
|
* @param nightMode true, if the device should be in the night mode, false if should not.
|
|
* @param rightToLeft true, if the device locale should be a right-to-left one, false if should not.
|
|
* @param smallestWidth the required smallest width of the screen.
|
|
*/
|
|
inline fun <T : Any> AnkoContext<*>.configuration(
|
|
screenSize: ScreenSize? = null,
|
|
density: ClosedRange<Int>? = null,
|
|
language: String? = null,
|
|
orientation: Orientation? = null,
|
|
long: Boolean? = null,
|
|
fromSdk: Int? = null,
|
|
sdk: Int? = null,
|
|
uiMode: UiMode? = null,
|
|
nightMode: Boolean? = null,
|
|
rightToLeft: Boolean? = null,
|
|
smallestWidth: Int? = null,
|
|
f: () -> T,
|
|
): T? = if (AnkoInternals.testConfiguration(
|
|
ctx, screenSize, density, language, orientation, long,
|
|
fromSdk, sdk, uiMode, nightMode, rightToLeft, smallestWidth
|
|
)
|
|
) f() else null
|
|
|
|
/**
|
|
* Execute [f] if the device configuration matches all given constraints.
|
|
* You can use named arguments to provide only the relevant constraints.
|
|
* All null constraints are ignored.
|
|
*
|
|
* @param screenSize the required screen size.
|
|
* @param density the required screen density.
|
|
* @param language the required system language.
|
|
* @param orientation the current screen orientation.
|
|
* @param long true, if the screen layout is long. See Configuration.SCREENLAYOUT_LONG_YES for more information.
|
|
* @param fromSdk the minimal SDK version for code to execute.
|
|
* @param sdk the target SDK version. Code will not be executed if the device Android SDK version is different
|
|
* (lower or higher than the given value).
|
|
* @param uiMode the required interface mode.
|
|
* @param nightMode true, if the device should be in the night mode, false if should not.
|
|
* @param rightToLeft true, if the device locale should be a right-to-left one, false if should not.
|
|
* @param smallestWidth the required smallest width of the screen.
|
|
*/
|
|
@Deprecated(message = "Use support library fragments instead. Framework fragments were deprecated in API 28.")
|
|
inline fun <T : Any> Fragment.configuration(
|
|
screenSize: ScreenSize? = null,
|
|
density: ClosedRange<Int>? = null,
|
|
language: String? = null,
|
|
orientation: Orientation? = null,
|
|
long: Boolean? = null,
|
|
fromSdk: Int? = null,
|
|
sdk: Int? = null,
|
|
uiMode: UiMode? = null,
|
|
nightMode: Boolean? = null,
|
|
rightToLeft: Boolean? = null,
|
|
smallestWidth: Int? = null,
|
|
f: () -> T,
|
|
): T? {
|
|
val act = activity
|
|
return if (act != null) {
|
|
if (AnkoInternals.testConfiguration(
|
|
act, screenSize, density, language, orientation, long,
|
|
fromSdk, sdk, uiMode, nightMode, rightToLeft, smallestWidth
|
|
)
|
|
) f() else null
|
|
} else null
|
|
}
|
|
|
|
/**
|
|
* Execute [f] only if the current Android SDK version is [version] or older.
|
|
* Do nothing otherwise.
|
|
*/
|
|
inline fun doBeforeSdk(version: Int, f: () -> Unit) {
|
|
if (Build.VERSION.SDK_INT <= version) f()
|
|
}
|
|
|
|
/**
|
|
* Execute [f] only if the current Android SDK version is [version] or newer.
|
|
* Do nothing otherwise.
|
|
*/
|
|
@ChecksSdkIntAtLeast(parameter = 0, lambda = 1)
|
|
inline fun doFromSdk(version: Int, f: () -> Unit) {
|
|
if (Build.VERSION.SDK_INT >= version) f()
|
|
}
|
|
|
|
/**
|
|
* Execute [f] only if the current Android SDK version is [version].
|
|
* Do nothing otherwise.
|
|
*/
|
|
inline fun doIfSdk(version: Int, f: () -> Unit) {
|
|
if (Build.VERSION.SDK_INT == version) f()
|
|
}
|
|
|
|
/**
|
|
* Result of the [attempt] function.
|
|
* Either [value] or [error] is not null.
|
|
*
|
|
* @property value the return value if code execution was finished without an exception, null otherwise.
|
|
* @property error a caught [Throwable] or null if nothing was caught.
|
|
*/
|
|
data class AttemptResult<out T> @PublishedApi internal constructor(
|
|
val value: T?,
|
|
val error: Throwable?,
|
|
) {
|
|
inline fun <R> then(f: (T) -> R): AttemptResult<R> {
|
|
if (isError) {
|
|
@Suppress("UNCHECKED_CAST")
|
|
return this as AttemptResult<R>
|
|
}
|
|
|
|
return attempt {
|
|
@Suppress("UNCHECKED_CAST")
|
|
f(value as T)
|
|
}
|
|
}
|
|
|
|
inline val isError: Boolean
|
|
get() = error != null
|
|
|
|
inline val hasValue: Boolean
|
|
get() = error == null
|
|
}
|
|
|
|
/**
|
|
* Execute [f] and return the result or an exception, if an exception was occurred.
|
|
*/
|
|
inline fun <T> attempt(f: () -> T): AttemptResult<T> {
|
|
var value: T? = null
|
|
var error: Throwable? = null
|
|
try {
|
|
value = f()
|
|
} catch (t: Throwable) {
|
|
error = t
|
|
}
|
|
return AttemptResult(value, error)
|
|
}
|