diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3e69e39..b6b59b1 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -16,8 +16,10 @@
+
+
-
+
diff --git a/app/src/main/java/soko/ekibun/stitch/EditActivity.kt b/app/src/main/java/soko/ekibun/stitch/EditActivity.kt
index e5139df..a9b347e 100644
--- a/app/src/main/java/soko/ekibun/stitch/EditActivity.kt
+++ b/app/src/main/java/soko/ekibun/stitch/EditActivity.kt
@@ -19,6 +19,7 @@ import android.util.Log
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.*
+import androidx.core.view.setPadding
import androidx.core.widget.doAfterTextChanged
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
@@ -52,6 +53,56 @@ class EditActivity : Activity() {
private val numberB by lazy { findViewById(R.id.menu_edit_b) }
private val numberDiv by lazy { findViewById(R.id.menu_edit_divider) }
private val dropdown by lazy { findViewById(R.id.menu_dropdown) }
+ private val panelAuto by lazy { findViewById(R.id.panel_auto) }
+ private val panelSeekbar by lazy { findViewById(R.id.panel_seekbar) }
+ private val switchHorizon by lazy { findViewById(R.id.switch_horizon) }
+
+ private val tabviews by lazy {
+ findViewById(R.id.panel_tab).let { layout ->
+ val padding = (resources.displayMetrics.density * 16).roundToInt()
+ StitchType.values().mapIndexed { i, it ->
+ TextView(this).apply {
+ text = it.label
+ tag = it
+ textAlignment = TextView.TEXT_ALIGNMENT_CENTER
+ setPadding(padding)
+ setOnClickListener { _ ->
+ stitchType = it
+ updateSelectInfo()
+ }
+ layout.addView(
+ this, i, LinearLayout.LayoutParams(
+ 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f
+ )
+ )
+ }
+ }
+ }
+ }
+
+ fun updateTab() {
+ tabviews.forEach {
+ it.setBackgroundResource(if (it.tag == stitchType) R.color.opaque else 0)
+ }
+ when (stitchType) {
+ StitchType.AUTO -> {
+ panelSeekbar.visibility = View.GONE
+ panelAuto.visibility = View.VISIBLE
+ }
+ StitchType.TILE -> {
+ panelSeekbar.visibility = View.VISIBLE
+ panelAuto.visibility = View.GONE
+ switchHorizon.visibility = View.VISIBLE
+ dropdown.visibility = View.GONE
+ }
+ StitchType.MAN -> {
+ panelSeekbar.visibility = View.VISIBLE
+ panelAuto.visibility = View.GONE
+ switchHorizon.visibility = View.GONE
+ dropdown.visibility = View.VISIBLE
+ }
+ }
+ }
data class SelectItemInfo(
val roundOf: Int,
@@ -69,6 +120,12 @@ class EditActivity : Activity() {
)
private var selectIndex = R.string.label_dy
+ enum class StitchType(var label: String) {
+ AUTO("自动"), TILE("平铺"), MAN("手动")
+ }
+
+ private var stitchType = StitchType.AUTO
+
private val projectKey by lazy { intent.extras!!.getString("project")!! }
val project by lazy { App.getProject(projectKey) }
@@ -79,7 +136,9 @@ class EditActivity : Activity() {
}
private fun updateNumberView(a: Float? = null, b: Float? = null) {
- val (roundOf, showB) = selectItems[selectIndex] ?: (0 to false)
+ val (roundOf, showB) = if (stitchType == StitchType.MAN)
+ selectItems[selectIndex] ?: (0 to false)
+ else (2 to true)
numberB.visibility = if (showB) View.VISIBLE else View.GONE
numberDiv.visibility = if (showB) View.VISIBLE else View.GONE
numberDec.visibility = if (showB) View.GONE else View.VISIBLE
@@ -109,7 +168,20 @@ class EditActivity : Activity() {
fun setNumber(a: Float? = null, b: Float? = null, relative: Boolean = false) {
val selected = selectedStitchInfo
if (selected.isNotEmpty()) selected.forEach {
- when (selectIndex) {
+ if (stitchType == StitchType.TILE) {
+ val aa = a ?: seekbar.a
+ val bb = b ?: seekbar.b
+ val rest = 1 - bb + aa
+ it.a = if (rest > 0) aa / rest else 0f
+ it.b = it.a
+ if (switchHorizon.isChecked) {
+ it.dx = (bb - aa) * it.width
+ it.dy = 0f
+ } else {
+ it.dy = (bb - aa) * it.height
+ it.dx = 0f
+ }
+ } else when (selectIndex) {
R.string.label_dx -> if (a != null) it.dx = if (relative) (a * 2 - 1) * it.width else a
R.string.label_dy -> if (a != null) it.dy = if (relative) (a * 2 - 1) * it.height else a
R.string.label_trim -> {
@@ -131,7 +203,7 @@ class EditActivity : Activity() {
}
private val selectedStitchInfo
- get() = when (selectIndex) {
+ get() = when (if (stitchType == StitchType.MAN) selectIndex else 0) {
R.string.label_dx,
R.string.label_dy,
R.string.label_trim -> project.stitchInfo.filterIndexed { i, v ->
@@ -144,7 +216,19 @@ class EditActivity : Activity() {
val selected = selectedStitchInfo
if (selected.isNotEmpty()) {
numberView.visibility = View.VISIBLE
- when (selectIndex) {
+ if (stitchType == StitchType.TILE) {
+ if (switchHorizon.isChecked) {
+ updateNumberView(
+ selected.map { (1 - it.dx / it.width) * it.a }.average().toFloat(),
+ selected.map { it.a + (1 - it.a) * (it.dx / it.width) }.average().toFloat()
+ )
+ } else {
+ updateNumberView(
+ selected.map { (1 - it.dy / it.height) * it.a }.average().toFloat(),
+ selected.map { it.a + (1 - it.a) * (it.dy / it.height) }.average().toFloat()
+ )
+ }
+ } else when (selectIndex) {
R.string.label_dx -> {
updateNumberView(selected.map { it.dx }.average().toFloat())
}
@@ -185,7 +269,16 @@ class EditActivity : Activity() {
val selected = selectedStitchInfo
if (selected.isNotEmpty()) {
seekbar.isEnabled = true
- when (selectIndex) {
+ if (stitchType == StitchType.TILE) {
+ seekbar.type = RangeSeekbar.TYPE_RANGE
+ if (switchHorizon.isChecked) {
+ seekbar.a = selected.map { (1 - it.dx / it.width) * it.a }.average().toFloat()
+ seekbar.b = selected.map { it.a + (1 - it.a) * (it.dx / it.width) }.average().toFloat()
+ } else {
+ seekbar.a = selected.map { (1 - it.dy / it.height) * it.a }.average().toFloat()
+ seekbar.b = selected.map { it.a + (1 - it.a) * (it.dy / it.height) }.average().toFloat()
+ }
+ } else when (selectIndex) {
R.string.label_dx -> {
seekbar.type = RangeSeekbar.TYPE_CENTER
seekbar.a = selected.map { (it.dx / it.width + 1) / 2 }.average().toFloat()
@@ -232,6 +325,7 @@ class EditActivity : Activity() {
invalidateView()
selectInfo.text =
getString(R.string.label_select, project.selected.size, project.stitchInfo.size)
+ updateTab()
updateSeekbar()
updateNumber()
}
@@ -479,6 +573,13 @@ class EditActivity : Activity() {
findViewById(R.id.switch_diff).isChecked
)
}
+ switchHorizon.setOnCheckedChangeListener { _, _ ->
+ project.updateUndo(switchHorizon) {
+ setNumber()
+ }
+ updateSeekbar()
+ invalidateView()
+ }
numberA.doAfterTextChanged {
if (!numberA.isFocused) return@doAfterTextChanged
val newNum = it?.toString()?.toFloatOrNull() ?: return@doAfterTextChanged
diff --git a/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt b/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt
index c60caa5..7de1ed1 100644
--- a/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt
+++ b/app/src/main/java/soko/ekibun/stitch/RangeSeekbar.kt
@@ -9,6 +9,7 @@ import android.graphics.Shader
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
+import android.widget.LinearLayout
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -168,6 +169,10 @@ class RangeSeekbar(context: Context?, attrs: AttributeSet?) : View(context, attr
when (event.action) {
MotionEvent.ACTION_DOWN -> {
parent.requestDisallowInterceptTouchEvent(true)
+ (layoutParams as? LinearLayout.LayoutParams)?.let { lp ->
+ lp.width = width
+ lp.weight = 0f
+ }
downX = event.x
downY = event.y
val ar = abs(downX - radius - (width - 2 * radius) * a)
@@ -179,6 +184,11 @@ class RangeSeekbar(context: Context?, attrs: AttributeSet?) : View(context, attr
}
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+ (layoutParams as? LinearLayout.LayoutParams)?.let { lp ->
+ lp.width = 0
+ lp.weight = 1f
+ }
+ requestLayout()
downObj = 0
onTouchUp?.invoke()
}
diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml
index 32414d1..5201c9a 100644
--- a/app/src/main/res/layout/activity_edit.xml
+++ b/app/src/main/res/layout/activity_edit.xml
@@ -87,10 +87,10 @@
@@ -137,11 +137,21 @@
+
+
+
+