Mercurial > cgi-bin > hgweb.cgi > SimpleResizer
comparison app/src/main/java/com/bartsent/simpleresizer/EditImage.kt @ 32:be08576794af
Replace static object with ViewModel.
author | David Barts <n5jrn@me.com> |
---|---|
date | Fri, 26 Feb 2021 14:26:50 -0800 |
parents | aacf7a856b5f |
children | bead5d7e8c69 |
comparison
equal
deleted
inserted
replaced
31:0023e6013dd9 | 32:be08576794af |
---|---|
19 import android.widget.ProgressBar | 19 import android.widget.ProgressBar |
20 import android.widget.Toast | 20 import android.widget.Toast |
21 import androidx.appcompat.app.AlertDialog | 21 import androidx.appcompat.app.AlertDialog |
22 import androidx.appcompat.app.AppCompatActivity | 22 import androidx.appcompat.app.AppCompatActivity |
23 import androidx.appcompat.widget.PopupMenu | 23 import androidx.appcompat.widget.PopupMenu |
24 import androidx.lifecycle.ViewModel | |
25 import androidx.lifecycle.ViewModelProvider | |
24 import androidx.preference.PreferenceManager | 26 import androidx.preference.PreferenceManager |
25 import com.bartsent.simpleresizer.databinding.ActivityEditImageBinding | 27 import com.bartsent.simpleresizer.databinding.ActivityEditImageBinding |
26 import com.bartsent.simpleresizer.lib.ThreadPools | 28 import com.bartsent.simpleresizer.lib.ThreadPools |
27 import com.bartsent.simpleresizer.lib.getScaledInstance | 29 import com.bartsent.simpleresizer.lib.getScaledInstance |
28 import java.io.File | 30 import java.io.File |
29 import java.io.IOException | 31 import java.io.IOException |
30 | 32 |
31 class EditImage : AppCompatActivity() { | 33 class EditImage : AppCompatActivity() { |
32 private object State { | 34 class State: ViewModel() { |
33 var uri: Uri? = null | 35 var uri: Uri? = null |
34 var bitmap: Bitmap? = null | 36 var bitmap: Bitmap? = null |
35 } | 37 } |
38 private lateinit var viewModel: State | |
36 | 39 |
37 private val STDDIMS = arrayOf<Int>(1600, 1280, 1024, 800, 640, 512, 400, 320).apply { | 40 private val STDDIMS = arrayOf<Int>(1600, 1280, 1024, 800, 640, 512, 400, 320).apply { |
38 sort() | 41 sort() |
39 } | 42 } |
40 | 43 |
43 override fun onCreate(savedInstanceState: Bundle?) { | 46 override fun onCreate(savedInstanceState: Bundle?) { |
44 super.onCreate(savedInstanceState) | 47 super.onCreate(savedInstanceState) |
45 binding = ActivityEditImageBinding.inflate(layoutInflater) | 48 binding = ActivityEditImageBinding.inflate(layoutInflater) |
46 setContentView(binding.root) | 49 setContentView(binding.root) |
47 PreferenceManager.setDefaultValues(applicationContext, R.xml.root_preferences, false) | 50 PreferenceManager.setDefaultValues(applicationContext, R.xml.root_preferences, false) |
51 viewModel = ViewModelProvider(this).get(State::class.java) | |
48 } | 52 } |
49 | 53 |
50 override fun onCreateOptionsMenu(menu: Menu?): Boolean { | 54 override fun onCreateOptionsMenu(menu: Menu?): Boolean { |
51 menuInflater.inflate(R.menu.menu_edit, menu) | 55 menuInflater.inflate(R.menu.menu_edit, menu) |
52 return super.onCreateOptionsMenu(menu) | 56 return super.onCreateOptionsMenu(menu) |
95 super.onResume() | 99 super.onResume() |
96 | 100 |
97 // Read the URI, die if we can't. | 101 // Read the URI, die if we can't. |
98 val imageUri = intent?.data ?: intent?.extras?.get(Intent.EXTRA_STREAM) as? Uri | 102 val imageUri = intent?.data ?: intent?.extras?.get(Intent.EXTRA_STREAM) as? Uri |
99 if (imageUri == null) { | 103 if (imageUri == null) { |
100 if (State.bitmap == null) | 104 if (viewModel.bitmap == null) |
101 showFatalError(getString(R.string.error_no_uri)) | 105 showFatalError(getString(R.string.error_no_uri)) |
102 else | 106 else |
103 setImage(State.bitmap!!) | 107 setImage(viewModel.bitmap!!) |
104 return | 108 return |
105 } | 109 } |
106 | 110 |
107 // User has opened a new image. | 111 // User has opened a new image. |
108 if (imageUri != State.uri) { | 112 if (imageUri != viewModel.uri) { |
109 State.uri = imageUri | 113 viewModel.uri = imageUri |
110 binding.progressBar.visibility = ProgressBar.VISIBLE | 114 binding.progressBar.visibility = ProgressBar.VISIBLE |
111 ThreadPools.WORKERS.execute { | 115 ThreadPools.WORKERS.execute { |
112 val newBitmap = contentResolver.openInputStream(imageUri).use { | 116 val newBitmap = contentResolver.openInputStream(imageUri).use { |
113 BitmapFactory.decodeStream(it) | 117 BitmapFactory.decodeStream(it) |
114 } | 118 } |
122 } | 126 } |
123 return | 127 return |
124 } | 128 } |
125 | 129 |
126 // Rotation (of the phone). | 130 // Rotation (of the phone). |
127 val oldBitmap = State.bitmap | 131 val oldBitmap = viewModel.bitmap |
128 if (oldBitmap != null) | 132 if (oldBitmap != null) |
129 setImage(oldBitmap) | 133 setImage(oldBitmap) |
130 } | 134 } |
131 | 135 |
132 private fun setImage(image: Bitmap): Unit { | 136 private fun setImage(image: Bitmap): Unit { |
133 binding.imageSize.text = getString(R.string.image_size_text, image.width, image.height) | 137 binding.imageSize.text = getString(R.string.image_size_text, image.width, image.height) |
134 binding.image.setImageBitmap(image) | 138 binding.image.setImageBitmap(image) |
135 State.bitmap = image | 139 viewModel.bitmap = image |
136 binding.root.invalidate() | 140 binding.root.invalidate() |
137 } | 141 } |
138 | 142 |
139 private fun unsetImage(): Unit { | 143 private fun unsetImage(): Unit { |
140 State.uri = null | 144 viewModel.uri = null |
141 State.bitmap = null | 145 viewModel.bitmap = null |
142 } | 146 } |
143 | 147 |
144 private val CUSTOM = 999998 | 148 private val CUSTOM = 999998 |
145 private val CANCEL = 999999 | 149 private val CANCEL = 999999 |
146 | 150 |
147 fun scaleClicked(view: View): Unit { | 151 fun scaleClicked(view: View): Unit { |
148 val (maxSize, horizontal) = State.bitmap!!.run { | 152 val (maxSize, horizontal) = viewModel.bitmap!!.run { |
149 if (width > height) Pair(width, true) else Pair(height, false) | 153 if (width > height) Pair(width, true) else Pair(height, false) |
150 } | 154 } |
151 PopupMenu(this, view).apply { | 155 PopupMenu(this, view).apply { |
152 menu.run { | 156 menu.run { |
153 STDDIMS.filter { it < maxSize }.forEach { major -> | 157 STDDIMS.filter { it < maxSize }.forEach { major -> |
178 new.setColorSpace(oldColorSpace) | 182 new.setColorSpace(oldColorSpace) |
179 } | 183 } |
180 } | 184 } |
181 | 185 |
182 private fun doScale(newMax: Int): Unit { | 186 private fun doScale(newMax: Int): Unit { |
183 val oldBitmap = State.bitmap!! | 187 val oldBitmap = viewModel.bitmap!! |
184 val factor = newMax.toDouble() / maxOf(oldBitmap.width, oldBitmap.height).toDouble() | 188 val factor = newMax.toDouble() / maxOf(oldBitmap.width, oldBitmap.height).toDouble() |
185 if (factor >= 1.0) { | 189 if (factor >= 1.0) { |
186 throw IllegalArgumentException("can only scale down") | 190 throw IllegalArgumentException("can only scale down") |
187 } | 191 } |
188 val scaleType = PreferenceManager.getDefaultSharedPreferences(applicationContext).getString( | 192 val scaleType = PreferenceManager.getDefaultSharedPreferences(applicationContext).getString( |
202 } | 206 } |
203 } | 207 } |
204 } | 208 } |
205 | 209 |
206 private fun showCustomScaleDialog(): Unit { | 210 private fun showCustomScaleDialog(): Unit { |
207 val image = State.bitmap!! | 211 val image = viewModel.bitmap!! |
208 val curMaxDim = maxOf(image.width, image.height) | 212 val curMaxDim = maxOf(image.width, image.height) |
209 val dialogView = layoutInflater.inflate(R.layout.dialog_custom_scale, null) | 213 val dialogView = layoutInflater.inflate(R.layout.dialog_custom_scale, null) |
210 AlertDialog.Builder(this).also { | 214 AlertDialog.Builder(this).also { |
211 it.setPositiveButton(R.string.ok_text) { dialog, _ -> | 215 it.setPositiveButton(R.string.ok_text) { dialog, _ -> |
212 val maxDim = dialogView.findViewById<EditText>(R.id.custom_scale)?.text.toString().toIntOrNull() | 216 val maxDim = dialogView.findViewById<EditText>(R.id.custom_scale)?.text.toString().toIntOrNull() |
249 show() | 253 show() |
250 } | 254 } |
251 } | 255 } |
252 | 256 |
253 private fun doRotate(deg: Int): Unit { | 257 private fun doRotate(deg: Int): Unit { |
254 val oldBitmap = State.bitmap!! | 258 val oldBitmap = viewModel.bitmap!! |
255 if (deg % 90 != 0) { | 259 if (deg % 90 != 0) { |
256 throw IllegalArgumentException("$deg not a multiple of 90") | 260 throw IllegalArgumentException("$deg not a multiple of 90") |
257 } | 261 } |
258 val (w, h) = if (deg % 180 == 0) Pair(oldBitmap.width, oldBitmap.height) else Pair(oldBitmap.height, oldBitmap.width) | 262 val (w, h) = if (deg % 180 == 0) Pair(oldBitmap.width, oldBitmap.height) else Pair(oldBitmap.height, oldBitmap.width) |
259 val rotater = Matrix().apply { | 263 val rotater = Matrix().apply { |
278 unsetImage() | 282 unsetImage() |
279 finish() | 283 finish() |
280 } | 284 } |
281 | 285 |
282 fun doneClicked(view: View): Unit { | 286 fun doneClicked(view: View): Unit { |
283 val image = State.bitmap!! | 287 val image = viewModel.bitmap!! |
284 binding.progressBar.visibility = ProgressBar.VISIBLE | 288 binding.progressBar.visibility = ProgressBar.VISIBLE |
285 ThreadPools.WORKERS.execute { | 289 ThreadPools.WORKERS.execute { |
286 val contentValues = ContentValues().apply { | 290 val contentValues = ContentValues().apply { |
287 var fileName = getFileName(State.uri!!) | 291 var fileName = getFileName(viewModel.uri!!) |
288 if (fileName == null) { | 292 if (fileName == null) { |
289 val d = java.util.Date() | 293 val d = java.util.Date() |
290 fileName = "IMG_%tY%tm%td_%tH%tM%tS".format(d, d, d, d, d, d) | 294 fileName = "IMG_%tY%tm%td_%tH%tM%tS".format(d, d, d, d, d, d) |
291 } | 295 } |
292 val dot = fileName.lastIndexOf('.') | 296 val dot = fileName.lastIndexOf('.') |