|
@@ -1,6 +1,11 @@
|
|
|
package com.grkj.iscs_mars.view.widget
|
|
package com.grkj.iscs_mars.view.widget
|
|
|
|
|
|
|
|
-import android.graphics.*
|
|
|
|
|
|
|
+import android.graphics.Bitmap
|
|
|
|
|
+import android.graphics.Canvas
|
|
|
|
|
+import android.graphics.Color
|
|
|
|
|
+import android.graphics.Matrix
|
|
|
|
|
+import android.graphics.Paint
|
|
|
|
|
+import android.graphics.PointF
|
|
|
import android.os.SystemClock
|
|
import android.os.SystemClock
|
|
|
import android.view.MotionEvent
|
|
import android.view.MotionEvent
|
|
|
import androidx.core.content.ContextCompat
|
|
import androidx.core.content.ContextCompat
|
|
@@ -10,7 +15,6 @@ import com.grkj.iscs_mars.modbus.DockBean
|
|
|
import com.onlylemi.mapview.library.MapView
|
|
import com.onlylemi.mapview.library.MapView
|
|
|
import com.onlylemi.mapview.library.layer.MapBaseLayer
|
|
import com.onlylemi.mapview.library.layer.MapBaseLayer
|
|
|
import kotlin.math.abs
|
|
import kotlin.math.abs
|
|
|
-import kotlin.math.sin
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 自定义开关层(保持对外 API 兼容):
|
|
* 自定义开关层(保持对外 API 兼容):
|
|
@@ -52,14 +56,20 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
// ===== 同步 & 选择 =====
|
|
// ===== 同步 & 选择 =====
|
|
|
private val dataLock = Any()
|
|
private val dataLock = Any()
|
|
|
|
|
|
|
|
- @Volatile private var selectedEntityIdForKeep: Long? = null
|
|
|
|
|
- @Volatile private var selectedNameForKeep: String? = null
|
|
|
|
|
|
|
+ @Volatile
|
|
|
|
|
+ private var selectedEntityIdForKeep: Long? = null
|
|
|
|
|
+ @Volatile
|
|
|
|
|
+ private var selectedNameForKeep: String? = null
|
|
|
|
|
|
|
|
- @Volatile private var selectToken: Long = 0L
|
|
|
|
|
- private inline fun withLiveToken(token: Long, block: () -> Unit) { if (token == selectToken) block() }
|
|
|
|
|
|
|
+ @Volatile
|
|
|
|
|
+ private var selectToken: Long = 0L
|
|
|
|
|
+ private inline fun withLiveToken(token: Long, block: () -> Unit) {
|
|
|
|
|
+ if (token == selectToken) block()
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// ===== 动画参数 =====
|
|
// ===== 动画参数 =====
|
|
|
- @Volatile var inDraw: Boolean = false
|
|
|
|
|
|
|
+ @Volatile
|
|
|
|
|
+ var inDraw: Boolean = false
|
|
|
private set
|
|
private set
|
|
|
|
|
|
|
|
private val breathePeriod = 1200f
|
|
private val breathePeriod = 1200f
|
|
@@ -104,13 +114,29 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
private val appCtx get() = MyApplication.instance!!.applicationContext
|
|
private val appCtx get() = MyApplication.instance!!.applicationContext
|
|
|
private val colOn by lazy { ContextCompat.getColor(appCtx, R.color.common_switch_enable) }
|
|
private val colOn by lazy { ContextCompat.getColor(appCtx, R.color.common_switch_enable) }
|
|
|
private val colOff by lazy { ContextCompat.getColor(appCtx, R.color.common_switch_disable) }
|
|
private val colOff by lazy { ContextCompat.getColor(appCtx, R.color.common_switch_disable) }
|
|
|
- private val colRed by lazy { runCatching { ContextCompat.getColor(appCtx, R.color.red_500) }.getOrDefault(Color.parseColor("#EF4444")) }
|
|
|
|
|
- private val colOrange by lazy { runCatching { ContextCompat.getColor(appCtx, R.color.orange_500) }.getOrDefault(Color.parseColor("#F97316")) }
|
|
|
|
|
|
|
+ private val colRed by lazy {
|
|
|
|
|
+ runCatching {
|
|
|
|
|
+ ContextCompat.getColor(
|
|
|
|
|
+ appCtx,
|
|
|
|
|
+ R.color.red_500
|
|
|
|
|
+ )
|
|
|
|
|
+ }.getOrDefault(Color.parseColor("#EF4444"))
|
|
|
|
|
+ }
|
|
|
|
|
+ private val colOrange by lazy {
|
|
|
|
|
+ runCatching {
|
|
|
|
|
+ ContextCompat.getColor(
|
|
|
|
|
+ appCtx,
|
|
|
|
|
+ R.color.orange_500
|
|
|
|
|
+ )
|
|
|
|
|
+ }.getOrDefault(Color.parseColor("#F97316"))
|
|
|
|
|
+ }
|
|
|
private val colSelectRing = Color.argb(180, 66, 133, 244)
|
|
private val colSelectRing = Color.argb(180, 66, 133, 244)
|
|
|
|
|
|
|
|
// 长按探测
|
|
// 长按探测
|
|
|
- private val longPressTimeoutMs: Long = android.view.ViewConfiguration.getLongPressTimeout().toLong()
|
|
|
|
|
- private val touchSlop: Float = android.view.ViewConfiguration.get(mapView?.context ?: appCtx).scaledTouchSlop * 1.5f
|
|
|
|
|
|
|
+ private val longPressTimeoutMs: Long =
|
|
|
|
|
+ android.view.ViewConfiguration.getLongPressTimeout().toLong()
|
|
|
|
|
+ private val touchSlop: Float =
|
|
|
|
|
+ android.view.ViewConfiguration.get(mapView?.context ?: appCtx).scaledTouchSlop * 1.5f
|
|
|
private val touchSlopSq: Float = touchSlop * touchSlop
|
|
private val touchSlopSq: Float = touchSlop * touchSlop
|
|
|
private var pendingLongPress = false
|
|
private var pendingLongPress = false
|
|
|
private var longPressTriggered = false
|
|
private var longPressTriggered = false
|
|
@@ -134,7 +160,8 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ===== 兼容原版:对外回调 =====
|
|
// ===== 兼容原版:对外回调 =====
|
|
|
- var onLongPressListener: ((point: IsolationPoint, screenX: Float, screenY: Float, mapX: Float, mapY: Float) -> Unit)? = null
|
|
|
|
|
|
|
+ var onLongPressListener: ((point: IsolationPoint, screenX: Float, screenY: Float, mapX: Float, mapY: Float) -> Unit)? =
|
|
|
|
|
+ null
|
|
|
|
|
|
|
|
init {
|
|
init {
|
|
|
paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL_AND_STROKE }
|
|
paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL_AND_STROKE }
|
|
@@ -178,12 +205,24 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
changedCenters.add(add.pos)
|
|
changedCenters.add(add.pos)
|
|
|
} else {
|
|
} else {
|
|
|
var dirty = false
|
|
var dirty = false
|
|
|
- if (!dst.pos.approxEq(src.pos)) { dst.pos = PointF(src.pos.x, src.pos.y); dirty = true }
|
|
|
|
|
- if (dst.status != src.status) { dst.status = src.status; dirty = true }
|
|
|
|
|
- if (dst.motorCode != src.motorCode) { dst.motorCode = src.motorCode; dirty = true }
|
|
|
|
|
- if (dst.pointNfc != src.pointNfc) { dst.pointNfc = src.pointNfc; dirty = true }
|
|
|
|
|
- if (dst.pointSerialNumber != src.pointSerialNumber) { dst.pointSerialNumber = src.pointSerialNumber; dirty = true }
|
|
|
|
|
- if (src.icon != null && dst.icon !== src.icon) { dst.icon = src.icon; dirty = true }
|
|
|
|
|
|
|
+ if (!dst.pos.approxEq(src.pos)) {
|
|
|
|
|
+ dst.pos = PointF(src.pos.x, src.pos.y); dirty = true
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dst.status != src.status) {
|
|
|
|
|
+ dst.status = src.status; dirty = true
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dst.motorCode != src.motorCode) {
|
|
|
|
|
+ dst.motorCode = src.motorCode; dirty = true
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dst.pointNfc != src.pointNfc) {
|
|
|
|
|
+ dst.pointNfc = src.pointNfc; dirty = true
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dst.pointSerialNumber != src.pointSerialNumber) {
|
|
|
|
|
+ dst.pointSerialNumber = src.pointSerialNumber; dirty = true
|
|
|
|
|
+ }
|
|
|
|
|
+ if (src.icon != null && dst.icon !== src.icon) {
|
|
|
|
|
+ dst.icon = src.icon; dirty = true
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
dst.isSelected = when {
|
|
dst.isSelected = when {
|
|
|
!keepSelection -> false
|
|
!keepSelection -> false
|
|
@@ -239,7 +278,8 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
if (w == 0 || h == 0) return
|
|
if (w == 0 || h == 0) return
|
|
|
val pts = floatArrayOf(point.x, point.y)
|
|
val pts = floatArrayOf(point.x, point.y)
|
|
|
mapView.currentMatrix.mapPoints(pts)
|
|
mapView.currentMatrix.mapPoints(pts)
|
|
|
- val x = pts[0]; val y = pts[1]
|
|
|
|
|
|
|
+ val x = pts[0];
|
|
|
|
|
+ val y = pts[1]
|
|
|
if (x + margin >= 0 && x - margin <= w && y + margin >= 0 && y - margin <= h) {
|
|
if (x + margin >= 0 && x - margin <= w && y + margin >= 0 && y - margin <= h) {
|
|
|
throttleInvalidate()
|
|
throttleInvalidate()
|
|
|
}
|
|
}
|
|
@@ -264,20 +304,25 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
MotionEvent.ACTION_MOVE -> {
|
|
MotionEvent.ACTION_MOVE -> {
|
|
|
lastScreenX = event.x; lastScreenY = event.y
|
|
lastScreenX = event.x; lastScreenY = event.y
|
|
|
if (pendingLongPress && !longPressTriggered) {
|
|
if (pendingLongPress && !longPressTriggered) {
|
|
|
val dx = event.x - downScreenX
|
|
val dx = event.x - downScreenX
|
|
|
val dy = event.y - downScreenY
|
|
val dy = event.y - downScreenY
|
|
|
- if (dx*dx + dy*dy > touchSlopSq) {
|
|
|
|
|
|
|
+ if (dx * dx + dy * dy > touchSlopSq) {
|
|
|
pendingLongPress = false
|
|
pendingLongPress = false
|
|
|
mapView.removeCallbacks(longPressRunnable)
|
|
mapView.removeCallbacks(longPressRunnable)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
MotionEvent.ACTION_UP -> {
|
|
MotionEvent.ACTION_UP -> {
|
|
|
mapView.removeCallbacks(longPressRunnable)
|
|
mapView.removeCallbacks(longPressRunnable)
|
|
|
- if (longPressTriggered) { pendingLongPress = false; longPressTriggered = false; currentPressed = null; return }
|
|
|
|
|
|
|
+ if (longPressTriggered) {
|
|
|
|
|
+ pendingLongPress = false; longPressTriggered = false; currentPressed =
|
|
|
|
|
+ null; return
|
|
|
|
|
+ }
|
|
|
val mp = screenToMap(event.x, event.y) ?: return
|
|
val mp = screenToMap(event.x, event.y) ?: return
|
|
|
val hit = hitTest(mp.x, mp.y) ?: return
|
|
val hit = hitTest(mp.x, mp.y) ?: return
|
|
|
val token = ++selectToken
|
|
val token = ++selectToken
|
|
@@ -287,10 +332,22 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
val eid = hit.entityId
|
|
val eid = hit.entityId
|
|
|
val name = hit.motorCode
|
|
val name = hit.motorCode
|
|
|
|
|
|
|
|
- currentMapCenter()?.let { cur -> mapView?.animateCenterOnPoint(cur.x, cur.y, clickZoomDurationMs, targetScale) }
|
|
|
|
|
|
|
+ currentMapCenter()?.let { cur ->
|
|
|
|
|
+ mapView?.animateCenterOnPoint(
|
|
|
|
|
+ cur.x,
|
|
|
|
|
+ cur.y,
|
|
|
|
|
+ clickZoomDurationMs,
|
|
|
|
|
+ targetScale
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
mapView?.postDelayed({
|
|
mapView?.postDelayed({
|
|
|
withLiveToken(token) {
|
|
withLiveToken(token) {
|
|
|
- mapView?.animateCenterOnPoint(targetCenter.x, targetCenter.y, clickCenterDurationMs, targetScale)
|
|
|
|
|
|
|
+ mapView?.animateCenterOnPoint(
|
|
|
|
|
+ targetCenter.x,
|
|
|
|
|
+ targetCenter.y,
|
|
|
|
|
+ clickCenterDurationMs,
|
|
|
|
|
+ targetScale
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
}, clickZoomDurationMs)
|
|
}, clickZoomDurationMs)
|
|
|
mapView?.postDelayed({
|
|
mapView?.postDelayed({
|
|
@@ -302,6 +359,7 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
}
|
|
}
|
|
|
}, clickZoomDurationMs + clickCenterDurationMs)
|
|
}, clickZoomDurationMs + clickCenterDurationMs)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
MotionEvent.ACTION_CANCEL -> {
|
|
MotionEvent.ACTION_CANCEL -> {
|
|
|
pendingLongPress = false
|
|
pendingLongPress = false
|
|
|
longPressTriggered = false
|
|
longPressTriggered = false
|
|
@@ -312,7 +370,12 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ================= 绘制 =================
|
|
// ================= 绘制 =================
|
|
|
- override fun draw(canvas: Canvas, currentMatrix: Matrix, currentZoom: Float, currentRotateDegrees: Float) {
|
|
|
|
|
|
|
+ override fun draw(
|
|
|
|
|
+ canvas: Canvas,
|
|
|
|
|
+ currentMatrix: Matrix,
|
|
|
|
|
+ currentZoom: Float,
|
|
|
|
|
+ currentRotateDegrees: Float
|
|
|
|
|
+ ) {
|
|
|
if (!isVisible || inDraw) return
|
|
if (!isVisible || inDraw) return
|
|
|
inDraw = true
|
|
inDraw = true
|
|
|
this.currentZoom = currentZoom
|
|
this.currentZoom = currentZoom
|
|
@@ -345,14 +408,17 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
paint.color = colOn; paint.alpha = 255
|
|
paint.color = colOn; paint.alpha = 255
|
|
|
canvas.drawCircle(c.x, c.y, mapR, paint)
|
|
canvas.drawCircle(c.x, c.y, mapR, paint)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
STATUS_OFF -> {
|
|
STATUS_OFF -> {
|
|
|
paint.color = colOff; paint.alpha = 255
|
|
paint.color = colOff; paint.alpha = 255
|
|
|
canvas.drawCircle(c.x, c.y, mapR, paint)
|
|
canvas.drawCircle(c.x, c.y, mapR, paint)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
STATUS_ALARM -> {
|
|
STATUS_ALARM -> {
|
|
|
val t = pulsePhase
|
|
val t = pulsePhase
|
|
|
val color = if (t < 0.5f) colRed else colOrange
|
|
val color = if (t < 0.5f) colRed else colOrange
|
|
|
- val a = (160 + 95 * kotlin.math.abs(kotlin.math.sin(2f * Math.PI.toFloat() * t))).toInt()
|
|
|
|
|
|
|
+ val a =
|
|
|
|
|
+ (160 + 95 * kotlin.math.abs(kotlin.math.sin(2f * Math.PI.toFloat() * t))).toInt()
|
|
|
paint.color = color; paint.alpha = a
|
|
paint.color = color; paint.alpha = a
|
|
|
val r = mapR * (1.0f + 0.10f * kotlin.math.sin(2f * Math.PI.toFloat() * t))
|
|
val r = mapR * (1.0f + 0.10f * kotlin.math.sin(2f * Math.PI.toFloat() * t))
|
|
|
canvas.drawCircle(c.x, c.y, r, paint)
|
|
canvas.drawCircle(c.x, c.y, r, paint)
|
|
@@ -360,6 +426,7 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
canvas.drawCircle(c.x, c.y, r * 1.25f, paint)
|
|
canvas.drawCircle(c.x, c.y, r * 1.25f, paint)
|
|
|
paint.alpha = 255
|
|
paint.alpha = 255
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
else -> {
|
|
else -> {
|
|
|
paint.color = Color.DKGRAY; paint.alpha = 200
|
|
paint.color = Color.DKGRAY; paint.alpha = 200
|
|
|
canvas.drawCircle(c.x, c.y, mapR, paint)
|
|
canvas.drawCircle(c.x, c.y, mapR, paint)
|
|
@@ -384,7 +451,13 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
paint.strokeWidth = 0f
|
|
paint.strokeWidth = 0f
|
|
|
paint.color = Color.WHITE
|
|
paint.color = Color.WHITE
|
|
|
val maxTextWidthScreen = (screenR * 2f) - 6f
|
|
val maxTextWidthScreen = (screenR * 2f) - 6f
|
|
|
- val screenTextSize = fitTextSizeScreen(paint, text, maxTextWidthScreen, screenTextMin, screenTextMax)
|
|
|
|
|
|
|
+ val screenTextSize = fitTextSizeScreen(
|
|
|
|
|
+ paint,
|
|
|
|
|
+ text,
|
|
|
|
|
+ maxTextWidthScreen,
|
|
|
|
|
+ screenTextMin,
|
|
|
|
|
+ screenTextMax
|
|
|
|
|
+ )
|
|
|
val mapTextSize = screenTextSize
|
|
val mapTextSize = screenTextSize
|
|
|
paint.textSize = mapTextSize
|
|
paint.textSize = mapTextSize
|
|
|
val textW = paint.measureText(text)
|
|
val textW = paint.measureText(text)
|
|
@@ -399,7 +472,13 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private fun fitTextSizeScreen(p: Paint, text: String, maxWidthScreenPx: Float, minSp: Float, maxSp: Float): Float {
|
|
|
|
|
|
|
+ private fun fitTextSizeScreen(
|
|
|
|
|
+ p: Paint,
|
|
|
|
|
+ text: String,
|
|
|
|
|
+ maxWidthScreenPx: Float,
|
|
|
|
|
+ minSp: Float,
|
|
|
|
|
+ maxSp: Float
|
|
|
|
|
+ ): Float {
|
|
|
if (text.isEmpty()) return minSp
|
|
if (text.isEmpty()) return minSp
|
|
|
// 在“屏幕像素语义”下先估字号,再回到 draw() 里除以 zoom 赋给 paint.textSize
|
|
// 在“屏幕像素语义”下先估字号,再回到 draw() 里除以 zoom 赋给 paint.textSize
|
|
|
p.textSize = maxSp
|
|
p.textSize = maxSp
|
|
@@ -414,7 +493,6 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// ================= 工具 =================
|
|
// ================= 工具 =================
|
|
|
private fun getSwitchR(): Float {
|
|
private fun getSwitchR(): Float {
|
|
|
// 保持原有 ratio 语义 + 轻微随 zoom 增益
|
|
// 保持原有 ratio 语义 + 轻微随 zoom 增益
|
|
@@ -462,8 +540,10 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
val c = centerOf(p)
|
|
val c = centerOf(p)
|
|
|
val dx = mapX - c.x
|
|
val dx = mapX - c.x
|
|
|
val dy = mapY - c.y
|
|
val dy = mapY - c.y
|
|
|
- val d2 = dx*dx + dy*dy
|
|
|
|
|
- if (d2 <= hitR2 && d2 < bestD2) { bestD2 = d2; hit = p }
|
|
|
|
|
|
|
+ val d2 = dx * dx + dy * dy
|
|
|
|
|
+ if (d2 <= hitR2 && d2 < bestD2) {
|
|
|
|
|
+ bestD2 = d2; hit = p
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
return hit
|
|
return hit
|
|
|
}
|
|
}
|
|
@@ -478,7 +558,13 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
val mv = mapView ?: return throttleInvalidate()
|
|
val mv = mapView ?: return throttleInvalidate()
|
|
|
var didPartial = false
|
|
var didPartial = false
|
|
|
runCatching {
|
|
runCatching {
|
|
|
- val m = mv.javaClass.getMethod("invalidateRect", Int::class.java, Int::class.java, Int::class.java, Int::class.java)
|
|
|
|
|
|
|
+ val m = mv.javaClass.getMethod(
|
|
|
|
|
+ "invalidateRect",
|
|
|
|
|
+ Int::class.java,
|
|
|
|
|
+ Int::class.java,
|
|
|
|
|
+ Int::class.java,
|
|
|
|
|
+ Int::class.java
|
|
|
|
|
+ )
|
|
|
for (c in centers) {
|
|
for (c in centers) {
|
|
|
val l = (c.x - radiusPx).toInt()
|
|
val l = (c.x - radiusPx).toInt()
|
|
|
val t = (c.y - radiusPx).toInt()
|
|
val t = (c.y - radiusPx).toInt()
|
|
@@ -513,6 +599,7 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
if (isAlarm(bean)) return STATUS_ALARM
|
|
if (isAlarm(bean)) return STATUS_ALARM
|
|
|
return if (bean.enabled) STATUS_ON else STATUS_OFF
|
|
return if (bean.enabled) STATUS_ON else STATUS_OFF
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
private fun isAlarm(bean: DockBean.SwitchBean?): Boolean {
|
|
private fun isAlarm(bean: DockBean.SwitchBean?): Boolean {
|
|
|
// TODO: 按业务判断
|
|
// TODO: 按业务判断
|
|
|
return false
|
|
return false
|
|
@@ -521,7 +608,13 @@ class CustomSwitchStationLayer @JvmOverloads constructor(
|
|
|
private fun deepCopyPoint(p: PointF) = PointF(p.x, p.y)
|
|
private fun deepCopyPoint(p: PointF) = PointF(p.x, p.y)
|
|
|
private fun deepCopyItem(it: IsolationPoint) = it.copy(pos = deepCopyPoint(it.pos))
|
|
private fun deepCopyItem(it: IsolationPoint) = it.copy(pos = deepCopyPoint(it.pos))
|
|
|
|
|
|
|
|
- private fun fitTextSize(p: Paint, text: String, maxWidth: Float, minSp: Float = 8f, maxSp: Float = 22f): Float {
|
|
|
|
|
|
|
+ private fun fitTextSize(
|
|
|
|
|
+ p: Paint,
|
|
|
|
|
+ text: String,
|
|
|
|
|
+ maxWidth: Float,
|
|
|
|
|
+ minSp: Float = 8f,
|
|
|
|
|
+ maxSp: Float = 22f
|
|
|
|
|
+ ): Float {
|
|
|
if (text.isEmpty()) return minSp
|
|
if (text.isEmpty()) return minSp
|
|
|
p.textSize = maxSp
|
|
p.textSize = maxSp
|
|
|
var w = p.measureText(text)
|
|
var w = p.measureText(text)
|