炮塔拖拽初步

This commit is contained in:
coldmint 2022-08-19 14:51:28 +08:00
parent 24d9faba32
commit ed60f78d35
87 changed files with 2622 additions and 1473 deletions

Binary file not shown.

View File

@ -68,6 +68,9 @@ android {
dependencies { dependencies {
def nav_version = "2.5.1"
implementation 'com.leinardi.android:speed-dial:3.1.1'
// implementation 'com.luolc:emoji-rain:0.1.1' // implementation 'com.luolc:emoji-rain:0.1.1'
implementation 'me.zhanghai.android.fastscroll:library:1.1.8' implementation 'me.zhanghai.android.fastscroll:library:1.1.8'
// https://github.com/getActivity/MultiLanguages // https://github.com/getActivity/MultiLanguages
@ -91,26 +94,24 @@ dependencies {
implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.core:core-ktx:1.8.0'
implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4' implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4'
implementation 'com.google.code.gson:gson:2.9.1' implementation 'com.google.code.gson:gson:2.9.1'
implementation 'com.github.yalantis:ucrop:2.2.6-native' implementation 'com.github.yalantis:ucrop:2.2.8-native'
implementation 'com.kongzue.stacklabel:stacklabelview:1.1.9' implementation 'com.kongzue.stacklabel:stacklabelview:1.1.9'
implementation 'io.github.Rosemoe.sora-editor:editor:0.16.5' implementation 'io.github.Rosemoe.sora-editor:editor:0.16.5'
implementation project(path: ':assistantCoreLibrary') implementation project(path: ':assistantCoreLibrary')
implementation project(path: ':turretsDragView')
implementation project(path: ':dialog') implementation project(path: ':dialog')
implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0' implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0'
implementation 'com.afollestad.material-dialogs:input:3.3.0' implementation 'com.afollestad.material-dialogs:input:3.3.0'
implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.github.florent37:glidepalette:2.1.2' implementation 'com.github.florent37:glidepalette:2.1.2'
implementation 'com.github.QuadFlask:colorpicker:0.0.15' implementation 'com.github.QuadFlask:colorpicker:0.0.15'
implementation 'cat.ereza:customactivityoncrash:2.3.0' implementation 'cat.ereza:customactivityoncrash:2.3.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation 'androidx.appcompat:appcompat:1.4.0' implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'com.google.android.material:material:1.6.1' implementation 'com.google.android.material:material:1.7.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5' implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5' implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.preference:preference-ktx:1.2.0'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'

View File

@ -24,6 +24,9 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.rust.Concept" android:theme="@style/Theme.rust.Concept"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<activity
android:name=".CustomizeEditTextActivity"
android:exported="false" />
<activity <activity
android:name=".SearchActivity" android:name=".SearchActivity"
android:exported="false" /> android:exported="false" />
@ -262,9 +265,9 @@
<activity <activity
android:name=".EditActivity" android:name=".EditActivity"
android:exported="true" android:exported="true"
android:windowSoftInputMode="adjustResize"
android:label="@string/mod_action1" android:label="@string/mod_action1"
android:screenOrientation="portrait" /> android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
<activity <activity
android:name=".CreateModActivity" android:name=".CreateModActivity"
android:screenOrientation="portrait" /> android:screenOrientation="portrait" />

View File

@ -4,10 +4,7 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.text.Html import android.text.Html
import android.view.LayoutInflater import android.view.*
import android.view.Menu
import android.view.MenuItem
import android.view.View
import com.coldmint.rust.core.web.ServerConfiguration import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.pro.base.BaseActivity import com.coldmint.rust.pro.base.BaseActivity
import com.coldmint.rust.pro.databinding.ActivityAboutBinding import com.coldmint.rust.pro.databinding.ActivityAboutBinding
@ -96,7 +93,7 @@ class AboutActivity : BaseActivity<ActivityAboutBinding>() {
} }
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_about, menu) menuInflater.inflate(R.menu.menu_about, menu)
return true return true
} }

View File

@ -86,7 +86,7 @@ class ActivateActivity : BaseActivity<ActivityActivateBinding>() {
* @param menu Menu * @param menu Menu
* @return Boolean * @return Boolean
*/ */
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater val inflater = menuInflater
inflater.inflate(R.menu.menu_pay, menu) inflater.inflate(R.menu.menu_pay, menu)
return true return true

View File

@ -63,10 +63,10 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>() {
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater val inflater = menuInflater
inflater.inflate(R.menu.menu_browser, menu) inflater.inflate(R.menu.menu_browser, menu)
return super.onCreateOptionsMenu(menu) return true
} }
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {

View File

@ -0,0 +1,403 @@
package com.coldmint.rust.pro
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MenuItem
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.isVisible
import androidx.palette.graphics.Palette
import com.afollestad.materialdialogs.utils.MDUtil.getWidthAndHeight
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions.bitmapTransform
import com.coldmint.dialog.CoreDialog
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.pro.base.BaseActivity
import com.coldmint.rust.pro.databinding.ActivityCustomizeEditTextBinding
import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.GlobalMethod
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.yalantis.ucrop.UCrop
import jp.wasabeef.glide.transformations.BlurTransformation
import java.io.File
class CustomizeEditTextActivity : BaseActivity<ActivityCustomizeEditTextBinding>() {
private lateinit var selectFile: ActivityResultLauncher<Intent>
private var clipPath: String? = null
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
setReturnButton()
title = getString(R.string.customize_edit_text)
readData()
loadAction()
val enable = AppSettings.getValue(
AppSettings.Setting.CodeEditBackGroundEnable,
false
)
if (enable) {
loadImage(
AppSettings.getValue(AppSettings.Setting.CodeEditBackGroundPath, ""),
AppSettings.getValue(AppSettings.Setting.BlurTransformationValue, 1)
)
}
selectFile = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
val key = "选择文件"
if (it.resultCode == RESULT_OK) {
//选择了文件
val intent = it.data
val path = intent?.getStringExtra("File") ?: ""
val file = File(path)
if (file.exists()) {
val type = FileOperator.getFileType(file)
if (type == "png" || type == "jpg") {
val bitmap = BitmapFactory.decodeFile(path)
val width = windowManager.getWidthAndHeight().first
val height = windowManager.getWidthAndHeight().second
val imageWidth = bitmap.width
val imageHeight = bitmap.height
if (width % imageWidth == 0 && height % imageHeight == 0) {
//可以被整除
DebugHelper.printLog(key, "图像无需裁剪。")
} else {
clipPath = AppSettings.createNewCodeEditBackGroundFile()
val newFile = File(clipPath)
DebugHelper.printLog(key, "前往裁剪 输出路径:${newFile.absolutePath}")
UCrop.of(
Uri.parse(file.toURI().toString()),
Uri.parse(newFile.toURI().toString())
)
.withAspectRatio(width.toFloat(), height.toFloat())
.start(this);
}
} else {
DebugHelper.printLog(key, "文件格式不合法", isError = true)
Snackbar.make(
viewBinding.button,
R.string.bad_file_type,
Snackbar.LENGTH_SHORT
).show()
}
} else {
DebugHelper.printLog(key, "文件不存在", isError = true)
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) {
// val resultUri = UCrop.getOutput(data!!)
if (clipPath != null) {
loadImage(clipPath!!)
} else {
Snackbar.make(
viewBinding.button,
R.string.bad_file_type,
Snackbar.LENGTH_SHORT
).show()
}
} else if (resultCode == UCrop.RESULT_ERROR) {
// val cropError = UCrop.getError(data!!)
Snackbar.make(
viewBinding.button,
R.string.bad_file_type,
Snackbar.LENGTH_SHORT
).show()
}
}
/**
* 加载图像
* @param filePath String
*/
fun loadImage(filePath: String, value: Int = 1) {
DebugHelper.printLog("加载文件", "加载了文件${filePath} 模糊度${value}", isError = true)
Glide.with(this).load(filePath).apply(
bitmapTransform(
BlurTransformation(value)
)
).into(viewBinding.imageView)
viewBinding.filePathInputEdit.setText(filePath)
viewBinding.imageCardView.isVisible = true
viewBinding.dimCardView.isVisible = true
viewBinding.autoGenerateColorSchemeButton.isVisible = true
viewBinding.slide.value = value.toFloat()
viewBinding.filePathInputLayout.endIconDrawable =
getDrawable(R.drawable.ic_outline_clear_24)
}
/**
* 读取数据
*/
fun readData() {
//读取内容
setTextAndColor(
viewBinding.textColorEditText,
AppSettings.getValue(AppSettings.Setting.TextColor, "")
)
setTextAndColor(
viewBinding.annotationColorEditText,
AppSettings.getValue(AppSettings.Setting.AnnotationColor, "")
)
setTextAndColor(
viewBinding.keywordColorEditText,
AppSettings.getValue(AppSettings.Setting.KeywordColor, "")
)
setTextAndColor(
viewBinding.sectionColorEditText,
AppSettings.getValue(AppSettings.Setting.SectionColor, "")
)
}
/**
* 加载事件
*/
fun loadAction() {
viewBinding.autoGenerateColorSchemeButton.setOnClickListener {
val bitmap = BitmapFactory.decodeFile(viewBinding.filePathInputEdit.text.toString())
Palette.from(bitmap).generate {
//充满活力的
setTextAndColor(
viewBinding.sectionColorEditText,
GlobalMethod.colorToString(it?.getVibrantColor(Color.RED) ?: Color.RED)
)
setTextAndColor(
viewBinding.annotationColorEditText,
GlobalMethod.colorToString(it?.getLightVibrantColor(Color.RED) ?: Color.RED)
)
setTextAndColor(
viewBinding.textColorEditText,
GlobalMethod.colorToString(it?.getDarkMutedColor(Color.RED) ?: Color.RED)
)
setTextAndColor(
viewBinding.keywordColorEditText,
GlobalMethod.colorToString(it?.getMutedColor(Color.RED) ?: Color.RED)
)
}
}
viewBinding.filePathInputLayout.setEndIconOnClickListener {
val oldFileData = viewBinding.filePathInputEdit.text.toString()
if (oldFileData.isBlank()) {
val intent = Intent(this, FileManagerActivity::class.java)
val bundle = Bundle()
bundle.putString("type", "selectFile")
intent.putExtra("data", bundle)
selectFile.launch(intent)
} else {
viewBinding.filePathInputEdit.setText("")
viewBinding.filePathInputLayout.endIconDrawable = getDrawable(R.drawable.file)
viewBinding.imageCardView.isVisible = false
viewBinding.dimCardView.isVisible = false
viewBinding.autoGenerateColorSchemeButton.isVisible = false
}
}
viewBinding.slide.addOnChangeListener { slider, value, fromUser ->
val filePath = viewBinding.filePathInputEdit.text.toString()
Glide.with(this).load(filePath).apply(
bitmapTransform(
BlurTransformation(value.toInt())
)
).into(viewBinding.imageView)
}
viewBinding.keywordColorEditLayout.setEndIconOnClickListener {
GlobalMethod.showColorPickerDialog(this, true) {
setTextAndColor(viewBinding.keywordColorEditText, it)
}
}
viewBinding.textColorEditLayout.setEndIconOnClickListener {
GlobalMethod.showColorPickerDialog(this, true) {
setTextAndColor(viewBinding.textColorEditText, it)
}
}
viewBinding.sectionColorEditLayout.setEndIconOnClickListener {
GlobalMethod.showColorPickerDialog(this, true) {
setTextAndColor(viewBinding.sectionColorEditText, it)
}
}
viewBinding.annotationColorEditLayout.setEndIconOnClickListener {
GlobalMethod.showColorPickerDialog(this, true) {
setTextAndColor(viewBinding.annotationColorEditText, it)
}
}
viewBinding.resetButton.setOnClickListener {
setTextAndColor(viewBinding.keywordColorEditText, "#FF0031C2")
setTextAndColor(viewBinding.sectionColorEditText, "#FFE10000")
setTextAndColor(viewBinding.textColorEditText, "#FF000000")
setTextAndColor(viewBinding.annotationColorEditText, "#FF00AF2C")
}
viewBinding.button.setOnClickListener {
saveData()
finish()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
showSaveDialogIfNeed()
}
return super.onOptionsItemSelected(item)
}
fun showSaveDialogIfNeed() {
val needSave = needSave()
if (needSave) {
CoreDialog(this).setTitle(R.string.customize_edit_text)
.setMessage(R.string.save_settings).setPositiveButton(R.string.dialog_ok) {
saveData()
finish()
}.setNegativeButton(R.string.dialog_cancel) {
finish()
}.setCancelable(false).show()
} else {
finish()
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) {
showSaveDialogIfNeed()
return true
}
return super.onKeyDown(keyCode, event)
}
/**
* 是否需要保存
* @return Boolean
*/
fun needSave(): Boolean {
val textColor = AppSettings.getValue(
AppSettings.Setting.TextColor,
""
)
if (viewBinding.textColorEditText.text.toString() != textColor) {
return true
}
val annotationColor = AppSettings.getValue(
AppSettings.Setting.AnnotationColor,
""
)
if (viewBinding.annotationColorEditText.text.toString() != annotationColor) {
return true
}
val keywordColor = AppSettings.getValue(
AppSettings.Setting.KeywordColor,
""
)
if (viewBinding.keywordColorEditText.text.toString() != keywordColor) {
return true
}
val sectionColor = AppSettings.getValue(
AppSettings.Setting.SectionColor,
""
)
if (viewBinding.sectionColorEditText.text.toString() != sectionColor) {
return true
}
val blurTransformationValue = AppSettings.getValue(
AppSettings.Setting.BlurTransformationValue,
1
)
if (viewBinding.slide.value.toInt() != blurTransformationValue) {
return true
}
val codeEditBackGroundPath =
AppSettings.getValue(AppSettings.Setting.CodeEditBackGroundPath, "")
if (viewBinding.filePathInputEdit.text.toString() != codeEditBackGroundPath) {
return true
}
return false
}
/**
* 保存用户数据
*/
fun saveData() {
AppSettings.setValue(
AppSettings.Setting.TextColor,
viewBinding.textColorEditText.text.toString()
)
AppSettings.setValue(
AppSettings.Setting.AnnotationColor,
viewBinding.annotationColorEditText.text.toString()
)
AppSettings.setValue(
AppSettings.Setting.KeywordColor,
viewBinding.keywordColorEditText.text.toString()
)
AppSettings.setValue(
AppSettings.Setting.SectionColor,
viewBinding.sectionColorEditText.text.toString()
)
AppSettings.setValue(
AppSettings.Setting.BlurTransformationValue,
viewBinding.slide.value.toInt()
)
val filePath = viewBinding.filePathInputEdit.text.toString()
val enable = if (filePath.isNullOrBlank()) {
false
} else {
val file = File(filePath)
if (file.exists()) {
val newPath = AppSettings.createNewCodeEditBackGroundFile()
val newFile = File(newPath)
FileOperator.copyFile(file, newFile)
AppSettings.setValue(AppSettings.Setting.CodeEditBackGroundPath, newPath)
true
} else {
false
}
}
//如果输入了文件路径那么启用
AppSettings.setValue(
AppSettings.Setting.CodeEditBackGroundEnable,
enable
)
}
/**
* 设置文本和颜色
* @param textInputEditText TextInputEditText
*/
fun setTextAndColor(textInputEditText: TextInputEditText, color: String) {
try {
textInputEditText.setText(color)
textInputEditText.setTextColor(Color.parseColor(color))
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun getViewBindingObject(layoutInflater: LayoutInflater): ActivityCustomizeEditTextBinding {
return ActivityCustomizeEditTextBinding.inflate(layoutInflater)
}
}

View File

@ -1,8 +1,10 @@
package com.coldmint.rust.pro package com.coldmint.rust.pro
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -25,6 +27,11 @@ import com.afollestad.materialdialogs.input.getInputField
import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.input.input
import com.afollestad.materialdialogs.list.ItemListener import com.afollestad.materialdialogs.list.ItemListener
import com.afollestad.materialdialogs.list.listItems import com.afollestad.materialdialogs.list.listItems
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.request.transition.Transition
import com.coldmint.rust.core.AnalysisResult import com.coldmint.rust.core.AnalysisResult
import com.coldmint.rust.core.CodeCompiler2 import com.coldmint.rust.core.CodeCompiler2
import com.coldmint.rust.core.ModClass import com.coldmint.rust.core.ModClass
@ -62,6 +69,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import io.github.rosemoe.sora.lang.completion.CompletionItem import io.github.rosemoe.sora.lang.completion.CompletionItem
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
import jp.wasabeef.glide.transformations.BlurTransformation
import java.io.File import java.io.File
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -211,10 +219,10 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
// if (temCodeInfo == null) { // if (temCodeInfo == null) {
// //
// } else { // } else {
// val completionItemConverter = CompletionItemConverter.instance // val CompletionItemConverter = CompletionItemConverter.instance
// completionItemConverter.init(this) // CompletionItemConverter.init(this)
// list.add( // list.add(
// completionItemConverter.codeInfoToCompletionItem( // CompletionItemConverter.codeInfoToCompletionItem(
// temCodeInfo // temCodeInfo
// ) // )
// ) // )
@ -482,6 +490,7 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
initStartView() initStartView()
initEndView() initEndView()
showRenewalTip() showRenewalTip()
loadCustomStyle()
} else { } else {
val thisIntent = intent val thisIntent = intent
val bundle = thisIntent.getBundleExtra("data") val bundle = thisIntent.getBundleExtra("data")
@ -958,29 +967,9 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
codeToolAdapter.setItemEvent { i, codeToolItemBinding, viewHolder, item -> codeToolAdapter.setItemEvent { i, codeToolItemBinding, viewHolder, item ->
codeToolItemBinding.root.setOnClickListener { codeToolItemBinding.root.setOnClickListener {
if (item == getString(R.string.symbol11)) { if (item == getString(R.string.symbol11)) {
ColorPickerDialogBuilder GlobalMethod.showColorPickerDialog(this) {
.with(this@EditActivity) viewBinding.codeEditor.insertText(it, it.length)
.setTitle(getString(R.string.choose_color)) }
.initialColor(Color.WHITE)
.wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
.density(12)
.setOnColorSelectedListener {
//toast("onColorSelected: 0x" + Integer.toHexString(selectedColor));
}
.setPositiveButton(R.string.dialog_ok) { dialog, selectedColor, allColors ->
val r = Color.red(selectedColor)
val g = Color.green(selectedColor)
val b = Color.blue(selectedColor)
val builder = StringBuilder()
builder.append('#')
builder.append(viewModel.convertDigital(r))
builder.append(viewModel.convertDigital(g))
builder.append(viewModel.convertDigital(b))
viewBinding.codeEditor.insertText(builder.toString(), builder.length)
}
.setNegativeButton(R.string.dialog_cancel) { dialog, which -> }
.build()
.show()
} else if (item == getString(R.string.code_table)) { } else if (item == getString(R.string.code_table)) {
viewModel.needCheckAutoSave = false viewModel.needCheckAutoSave = false
startActivity(Intent(this@EditActivity, CodeTableActivity::class.java)) startActivity(Intent(this@EditActivity, CodeTableActivity::class.java))
@ -1065,11 +1054,11 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
// .findCodeByKeyFromSection(lineData, trueSection, number) // .findCodeByKeyFromSection(lineData, trueSection, number)
// } // }
// if (codeInfoList != null && codeInfoList.isNotEmpty()) { // if (codeInfoList != null && codeInfoList.isNotEmpty()) {
// val completionItemConverter = // val CompletionItemConverter =
// CompletionItemConverter.instance.init(this) // CompletionItemConverter.instance.init(this)
// codeInfoList.forEach { // codeInfoList.forEach {
// list.add( // list.add(
// completionItemConverter.codeInfoToCompletionItem( // CompletionItemConverter.codeInfoToCompletionItem(
// it // it
// ) // )
// ) // )
@ -1122,9 +1111,9 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
"JetBrainsMono-Regular.ttf" "JetBrainsMono-Regular.ttf"
) )
} }
val language = // val language =
AppSettings.getValue(AppSettings.Setting.AppLanguage, Locale.getDefault().language) // AppSettings.getValue(AppSettings.Setting.AppLanguage, Locale.getDefault().language)
rustLanguage = RustLanguage(this) rustLanguage = RustLanguage()
rustLanguage.setCodeDataBase(CodeDataBase.getInstance(this)) rustLanguage.setCodeDataBase(CodeDataBase.getInstance(this))
rustLanguage.setFileDataBase( rustLanguage.setFileDataBase(
FileDataBase.getInstance( FileDataBase.getInstance(
@ -1134,25 +1123,53 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
) )
// rustLanguage.setAnalyzerEnglishMode(viewModel.englishModeLiveData) // rustLanguage.setAnalyzerEnglishMode(viewModel.englishModeLiveData)
rustLanguage.setCodeEditor(viewBinding.codeEditor) rustLanguage.setCodeEditor(viewBinding.codeEditor)
val night = AppSettings.getValue(AppSettings.Setting.NightMode, false) viewBinding.codeEditor.setAutoCompletionItemAdapter(RustCompletionAdapter())
viewBinding.codeEditor.isVerticalScrollBarEnabled = false
val path = viewModel.modClass?.modFile?.absolutePath ?: ""
CompletionItemConverter.configurationFileConversion(
path,
"ROOT",
path
)
viewBinding.codeEditor.setEditorLanguage(rustLanguage)
}
/**
* 加载自动
*/
fun loadCustomStyle() {
val key = "加载自定义编辑框样式"
val editorColorScheme = EditorColorScheme() val editorColorScheme = EditorColorScheme()
val backgroundColor = GlobalMethod.getThemeColor(this, android.R.attr.windowBackground) val codeEditBackGroundEnable =
AppSettings.getValue(AppSettings.Setting.CodeEditBackGroundEnable, false)
val backgroundColor =
if (codeEditBackGroundEnable) {
DebugHelper.printLog(key, "启用背景图像,设置背景为透明。")
Color.TRANSPARENT
} else {
DebugHelper.printLog(key, "未启用背景图像,设置背景为窗口颜色。")
GlobalMethod.getThemeColor(this, android.R.attr.windowBackground)
}
//代码(可识别的关键字) //代码(可识别的关键字)
editorColorScheme.setColor( editorColorScheme.setColor(
EditorColorScheme.KEYWORD, EditorColorScheme.KEYWORD,
GlobalMethod.getThemeColor(this, android.R.attr.colorSecondary) Color.parseColor(AppSettings.getValue(AppSettings.Setting.KeywordColor, ""))
) )
//默认文本 //默认文本
editorColorScheme.setColor(EditorColorScheme.TEXT_NORMAL, Color.rgb(169, 183, 198)) editorColorScheme.setColor(
EditorColorScheme.TEXT_NORMAL,
Color.parseColor(AppSettings.getValue(AppSettings.Setting.TextColor, ""))
)
//注释 //注释
editorColorScheme.setColor( editorColorScheme.setColor(
EditorColorScheme.COMMENT, EditorColorScheme.COMMENT,
GlobalMethod.getThemeColor(this, android.R.attr.textColorTertiary) Color.parseColor(AppSettings.getValue(AppSettings.Setting.AnnotationColor, ""))
) )
//节 //节
editorColorScheme.setColor( editorColorScheme.setColor(
EditorColorScheme.FUNCTION_NAME, EditorColorScheme.FUNCTION_NAME,
GlobalMethod.getColorPrimary(this) Color.parseColor(AppSettings.getValue(AppSettings.Setting.SectionColor, ""))
) )
editorColorScheme.setColor( editorColorScheme.setColor(
EditorColorScheme.WHOLE_BACKGROUND, EditorColorScheme.WHOLE_BACKGROUND,
@ -1162,17 +1179,35 @@ class EditActivity : BaseActivity<ActivityEditBinding>() {
EditorColorScheme.LINE_NUMBER_BACKGROUND, EditorColorScheme.LINE_NUMBER_BACKGROUND,
backgroundColor backgroundColor
) )
viewBinding.codeEditor.colorScheme = editorColorScheme editorColorScheme.setColor(EditorColorScheme.COMPLETION_WND_BACKGROUND, backgroundColor)
viewBinding.codeEditor.setAutoCompletionItemAdapter(RustCompletionAdapter()) if (codeEditBackGroundEnable) {
viewBinding.codeEditor.isVerticalScrollBarEnabled = false //设置自定义背景图
val path = viewModel.modClass?.modFile?.absolutePath ?: "" Glide.with(this)
// rustLanguage.autoCompleteProvider.setConfigurationFileConversion( .load(AppSettings.getValue(AppSettings.Setting.CodeEditBackGroundPath, "")).apply(
// path, RequestOptions.bitmapTransform(
// "ROOT", BlurTransformation(
// path AppSettings.getValue(
// ) AppSettings.Setting.BlurTransformationValue,
viewBinding.codeEditor.setEditorLanguage(rustLanguage) 1
)
)
)
).into(object : CustomTarget<Drawable>() {
override fun onResourceReady(
resource: Drawable,
transition: Transition<in Drawable>?
) {
window.setBackgroundDrawable(resource)
}
override fun onLoadCleared(placeholder: Drawable?) {
}
})
}
viewBinding.codeEditor.colorScheme = editorColorScheme
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {

View File

@ -6,6 +6,7 @@ import com.coldmint.rust.core.ModClass
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop
@ -92,6 +93,19 @@ class EditModInfoActivity : BaseActivity<ActivityEditModInfoBinding>() {
} }
} }
/**
* 加载默认图像
*/
fun loadDefaultImage() {
val drawable = getDrawable(R.drawable.image)
viewBinding.iconView.setImageDrawable(
GlobalMethod.tintDrawable(
drawable,
ColorStateList.valueOf(GlobalMethod.getColorPrimary(this))
)
)
}
fun initData() { fun initData() {
val name = mModClass.readValueFromInfoSection("title", "mod") val name = mModClass.readValueFromInfoSection("title", "mod")
@ -103,8 +117,11 @@ class EditModInfoActivity : BaseActivity<ActivityEditModInfoBinding>() {
viewBinding.modDescribeEdit.setText(description) viewBinding.modDescribeEdit.setText(description)
} }
val bitmap = mModClass.modIcon val bitmap = mModClass.modIcon
if (bitmap != null) { if (bitmap == null) {
Glide.with(this@EditModInfoActivity).load(bitmap).apply(GlobalMethod.getRequestOptions()).into(viewBinding.iconView) loadDefaultImage()
} else {
Glide.with(this@EditModInfoActivity).load(bitmap)
.apply(GlobalMethod.getRequestOptions()).into(viewBinding.iconView)
mNeedIcon = true mNeedIcon = true
} }
val musicSourceFolder = mModClass.readValueFromInfoSection("sourceFolder", "music") val musicSourceFolder = mModClass.readValueFromInfoSection("sourceFolder", "music")
@ -269,7 +286,7 @@ class EditModInfoActivity : BaseActivity<ActivityEditModInfoBinding>() {
iconFile.delete() iconFile.delete()
mNeedIcon = false mNeedIcon = false
} }
viewBinding.iconView.setImageResource(R.drawable.image) loadDefaultImage()
} }
false false
} }
@ -356,7 +373,8 @@ class EditModInfoActivity : BaseActivity<ActivityEditModInfoBinding>() {
val bitmap = BitmapFactory.decodeFile(newIconFile.absolutePath) val bitmap = BitmapFactory.decodeFile(newIconFile.absolutePath)
if (bitmap.height == bitmap.width) { if (bitmap.height == bitmap.width) {
if (FileOperator.copyFile(newIconFile, iconFile)) { if (FileOperator.copyFile(newIconFile, iconFile)) {
Glide.with(this@EditModInfoActivity).load(newIconFile).apply(GlobalMethod.getRequestOptions()) Glide.with(this@EditModInfoActivity).load(newIconFile)
.apply(GlobalMethod.getRequestOptions())
.into(viewBinding.iconView) .into(viewBinding.iconView)
mNeedIcon = true mNeedIcon = true
} }
@ -369,7 +387,8 @@ class EditModInfoActivity : BaseActivity<ActivityEditModInfoBinding>() {
} }
} else if (requestCode == UCrop.REQUEST_CROP) { } else if (requestCode == UCrop.REQUEST_CROP) {
val resultUri = UCrop.getOutput(data) val resultUri = UCrop.getOutput(data)
Glide.with(this@EditModInfoActivity).load(resultUri).apply(GlobalMethod.getRequestOptions()).into(viewBinding.iconView) Glide.with(this@EditModInfoActivity).load(resultUri)
.apply(GlobalMethod.getRequestOptions()).into(viewBinding.iconView)
mNeedIcon = true mNeedIcon = true
} }
} }

View File

@ -15,6 +15,8 @@ import android.net.Uri
import android.os.* import android.os.*
import android.view.* import android.view.*
import android.widget.* import android.widget.*
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
@ -23,8 +25,11 @@ import com.afollestad.materialdialogs.actions.setActionButtonEnabled
import com.afollestad.materialdialogs.input.getInputField import com.afollestad.materialdialogs.input.getInputField
import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.input.input
import com.afollestad.materialdialogs.list.listItems import com.afollestad.materialdialogs.list.listItems
import com.afollestad.materialdialogs.utils.MDUtil.isLandscape
import com.bumptech.glide.Glide
import com.coldmint.dialog.CoreDialog import com.coldmint.dialog.CoreDialog
import com.coldmint.dialog.InputDialog import com.coldmint.dialog.InputDialog
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.core.tool.FileOperator import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.core.tool.LineParser import com.coldmint.rust.core.tool.LineParser
import com.coldmint.rust.pro.adapters.FileAdapter import com.coldmint.rust.pro.adapters.FileAdapter
@ -38,173 +43,17 @@ import com.google.android.material.chip.Chip
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.SnackbarContentLayout import com.google.android.material.snackbar.SnackbarContentLayout
import me.zhanghai.android.fastscroll.FastScrollerBuilder import me.zhanghai.android.fastscroll.FastScrollerBuilder
import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.InputStreamReader
import java.lang.Exception import java.lang.Exception
import java.util.* import java.util.*
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class FileManagerActivity : BaseActivity<ActivityFileBinding>() { class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
// private var directs = Environment.getExternalStorageDirectory()
// private var mRoot = directs
// var filePath = ""
//
// val executorService = Executors.newSingleThreadExecutor()
//
// //type可为默认default选择文件夹selectDirectents选择文件selectFile
// var mStartType: String? = "default"
// private var mFileAdapter: FileAdapter? = null
// private var mProcessFiles = false
// private var additionalData: String? = null
// private fun initView() {
// title = getString(R.string.file_manager)
// setReturnButton()
// viewBinding.fileList.layoutManager = LinearLayoutManager(this@FileManagerActivity)
// val intent = intent
// val bundle = intent.getBundleExtra("data")
// if (bundle == null) {
// showError("无效的请求。")
// finish()
// } else {
// mStartType = bundle.getString("type")
// when (mStartType) {
// "default" -> {
// }
// "selectDirectents" -> {
// setTitle(R.string.select_directents)
// viewBinding.fab.setIconResource(R.drawable.complete)
// viewBinding.fab.postDelayed({
// viewBinding.fab.text = getString(R.string.select_directents)
// viewBinding.fab.extend()
// }, 300)
// }
// "exportFile" -> {
// setTitle(R.string.export_file)
// val additional = bundle.getString("additionalData")
// if (additional == null) {
// showError("请输入 additionalData")
// return
// } else {
// viewBinding.fab.setIconResource(R.drawable.complete)
// viewBinding.fab.postDelayed({
// viewBinding.fab.text = getString(R.string.export_this)
// viewBinding.fab.extend()
// }, 300)
// }
// }
// "selectFile" -> {
// setTitle(R.string.select_file)
// viewBinding.fab.setIconResource(R.drawable.complete)
// viewBinding.fab.hide()
// }
// else -> {
// Toast.makeText(this, "意外的请求", Toast.LENGTH_SHORT).show()
// finish()
// }
// }
// if (bundle.containsKey("path")) {
// directs = File(bundle.getString("path"))
// }
// if (bundle.containsKey("rootpath")) {
// mRoot = File(bundle.getString("rootpath"))
// }
// if (bundle.containsKey("additionalData")) {
// additionalData = bundle.getString("additionalData")
// }
// }
// loadFiles(directs)
// }
//
// private fun tryOpenFile(file: File?) {
// if (file == null) {
// returnDirects()
// } else {
// if (file.isDirectory) {
// loadFiles(file)
// } else {
// when (mStartType) {
// "default" -> {
// when (FileOperator.getFileType(file)) {
// "ini", "txt", "template" -> {
// val bundle = Bundle()
// bundle.putString("path", file.absolutePath)
// bundle.putString("modPath", FileOperator.getSuperDirectory(file))
// val intent =
// Intent(this@FileManagerActivity, EditActivity::class.java)
// intent.putExtra("data", bundle)
// this@FileManagerActivity.startActivity(intent)
// }
// "json" -> {
// val openList = listOf<String>(
// getString(R.string.edit_template), getString(
// R.string.open_action1
// )
// )
// MaterialDialog(this).title(R.string.open_type)
// .listItems(items = openList) { dialog, offset, text ->
// when (text) {
// getString(R.string.edit_template) -> {
// editTemplate(file)
// }
// getString(R.string.open_action1) -> {
// editText(file)
// }
// }
// }.show()
//
// }
// "zip", "rwmod", "rar" -> {
// Toast.makeText(
// this@FileManagerActivity,
// "点击了压缩文件。",
// Toast.LENGTH_SHORT
// ).show()
// FileOperator.openFile(this@FileManagerActivity, file)
// }
// else -> {
// val ints = intArrayOf(
// R.string.open_action1,
// R.string.open_action4
// )
// val items = FileAdapter.conversionSymbol(
// this@FileManagerActivity,
// ints
// )
//
// MaterialAlertDialogBuilder(this).setItems(
// items
// ) { dialog, which ->
// when (ints[which]) {
// R.string.open_action1 -> {
// editText(file)
// }
// R.string.open_action4 -> FileOperator.openFile(
// this@FileManagerActivity,
// file
// )
// }
// }.show()
// }
// }
// viewBinding.fab.show()
// filePath = file.absolutePath
// }
// "selectFile" -> {
// viewBinding.fab.show()
// viewBinding.fab.postDelayed({
// filePath = file.absolutePath
// viewBinding.fab.text =
// String.format(getString(R.string.select_file_ok), file.name)
// viewBinding.fab.extend()
// }, 300)
//
// }
// }
// }
// }
// }
//
// //
// /** // /**
// * 编辑模板 // * 编辑模板
@ -238,219 +87,7 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
// intent.putExtra("data", bundle) // intent.putExtra("data", bundle)
// this@FileManagerActivity.startActivity(intent) // this@FileManagerActivity.startActivity(intent)
// } // }
//
// //加载文件
// fun loadFiles(file: File) {
// executorService.submit {
// if (!file.exists()) {
// runOnUiThread {
// viewBinding.fileList.isVisible = false
// viewBinding.progressBar.isVisible = false
// viewBinding.fileError.isVisible = true
// viewBinding.fileError.setText(R.string.unable_to_open_this_directory)
// viewBinding.fab.hide()
// }
// return@submit
// }
//
// if (file.isDirectory) {
// val files = file.listFiles()
// directs = file
// val fileArrayList: ArrayList<File?> = ArrayList(listOf(*files))
// if (file.absolutePath != mRoot.absolutePath) {
// fileArrayList.add(0, null)
// }
// val finalFileAdapter: FileAdapter =
// if (mFileAdapter == null) {
// mFileAdapter = FileAdapter(this@FileManagerActivity, fileArrayList)
// mFileAdapter!!
// } else {
// mFileAdapter?.setNewDataList(fileArrayList)
// mFileAdapter!!
// }
// finalFileAdapter.setSortType(FileAdapter.SortType.FileName)
// finalFileAdapter.setItemEvent { i, fileItemBinding, viewHolder, itemFile ->
// fileItemBinding.root.setOnClickListener {
// tryOpenFile(itemFile)
// }
// fileItemBinding.more.setOnClickListener {
// if (itemFile == null) {
// return@setOnClickListener
// }
// val popupMenu =
// PopupMenu(this@FileManagerActivity, fileItemBinding.more)
// val cutBoardMenu =
// popupMenu.menu.addSubMenu(R.string.cut_board_operation)
// val fileMenu = popupMenu.menu.addSubMenu(R.string.file_operation)
// val bookmarksMenu =
// popupMenu.menu.addSubMenu(R.string.bookmarks_operation)
// cutBoardMenu.add(R.string.copy_file_name)
// cutBoardMenu.add(R.string.copy_file_path)
// fileMenu.add(R.string.copy)
// fileMenu.add(R.string.cut_off)
// fileMenu.add(R.string.mod_action9)
// fileMenu.add(R.string.delete_title)
// if (bookmarkManager.contains(file)) {
// bookmarksMenu.add(R.string.remove_bookmark)
// } else {
// bookmarksMenu.add(R.string.add_bookmark)
// }
// bookmarksMenu.add(R.string.bookmark_manager)
// addJumpBookMenu(bookmarksMenu)
// popupMenu.setOnMenuItemClickListener { item ->
// val title = item.title
// if (title == getText(R.string.copy_file_name)) {
// val name = itemFile.name
// GlobalMethod.copyText(
// this@FileManagerActivity,
// name,
// viewBinding.fab
// )
// } else if (title == getText(R.string.copy_file_path)) {
// val path = itemFile.absolutePath
// GlobalMethod.copyText(
// this@FileManagerActivity,
// path,
// viewBinding.fab
// )
// } else if (title == getText(R.string.delete_title)) {
// executorService.submit {
// FileOperator.delete_files(itemFile)
// runOnUiThread {
// loadFiles(directs)
// }
// }
// } else if (title == getText(R.string.copy)) {
// finalFileAdapter.setSelectPath(itemFile.absolutePath, true)
// } else if (title == getText(R.string.cut_off)) {
// finalFileAdapter.setSelectPath(itemFile.absolutePath, false)
// } else if (title == getText(R.string.mod_action9)) {
// val oldName = itemFile.name
// MaterialDialog(this@FileManagerActivity).show {
// title(R.string.mod_action9)
// input(
// maxLength = 255,
// waitForPositiveButton = false, prefill = oldName
// ) { dialog, text ->
// if (text.length in 1..255) {
// dialog.setActionButtonEnabled(
// WhichButton.POSITIVE,
// true
// )
// }
// }.positiveButton(R.string.dialog_ok, null) { dialog ->
// val newName = dialog.getInputField().text.toString()
// if (!newName.isEmpty() || newName != oldName) {
// val reNameFile = File("$directs/$newName")
// itemFile.renameTo(reNameFile)
// loadFiles(directs)
// }
// }.negativeButton(R.string.dialog_close)
// }
// } else if (title == getString(R.string.remove_bookmark)) {
// val removeBookmark =
// bookmarkManager.removeBookmark(itemFile.absolutePath)
// if (removeBookmark) {
// Snackbar.make(
// viewBinding.fab,
// R.string.remove_bookmark_success,
// Snackbar.LENGTH_SHORT
// ).setAction(R.string.symbol10) {
// bookmarkManager.addBookmark(
// itemFile.absolutePath,
// FileOperator.getPrefixName(file)
// )
// }
// .show()
// } else {
// Snackbar.make(
// viewBinding.fab,
// R.string.remove_bookmark_fail,
// Snackbar.LENGTH_SHORT
// ).show()
// }
// } else if (title == getString(R.string.add_bookmark)) {
// val addBookmark = bookmarkManager.addBookmark(
// itemFile.absolutePath,
// FileOperator.getPrefixName(file)
// )
// if (addBookmark) {
// Snackbar.make(
// viewBinding.fab,
// R.string.add_bookmark_success,
// Snackbar.LENGTH_SHORT
// ).show()
// } else {
// Snackbar.make(
// viewBinding.fab,
// R.string.add_bookmark_fail,
// Snackbar.LENGTH_SHORT
// ).show()
// }
// } else if (title == getString(R.string.bookmark_manager)) {
// bookmarkManager.save()
// startActivity(
// Intent(
// this@FileManagerActivity,
// BookmarkManagerActivity::class.java
// )
// )
// } else {
// loadBook(title)
// }
// false
// }
// popupMenu.show()
// }
// }
// runOnUiThread {
// viewBinding.fileList.adapter = finalFileAdapter
// viewBinding.fileList.isVisible = true
// viewBinding.fileError.isVisible = false
// viewBinding.progressBar.isVisible = false
// }
// }
// }
// }
//
//
// /**
// * 点击书签项目
// */
// fun loadBook(menuTitle: CharSequence) {
// if (bookmarkMap.containsKey(menuTitle)) {
// val path = bookmarkMap[menuTitle]
// if (path != null) {
// val rootPath = viewModel.getRootPath()
// if (path.startsWith(rootPath)) {
// val newFile = File(path)
// if (newFile.exists()) {
// if (newFile.isDirectory) {
// viewModel.loadFiles(newFile.absolutePath)
// } else {
//// tryOpenFile(newFile)
// }
// } else {
// Snackbar.make(
// viewBinding.fab,
// R.string.bookmark_jump_failed,
// Snackbar.LENGTH_SHORT
// ).show()
// }
// } else {
// Snackbar.make(
// viewBinding.fab,
// R.string.cannot_be_accessed_this_directory,
// Snackbar.LENGTH_SHORT
// ).show()
// }
// }
//
// }
// }
//
//
// override fun onPause() { // override fun onPause() {
// viewModel.getBookmarkManager().save() // viewModel.getBookmarkManager().save()
// super.onPause() // super.onPause()
@ -461,10 +98,7 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
loadMineBookmarksMenu() loadMineBookmarksMenu()
super.onResume() super.onResume()
} }
//
//
//
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
@ -474,20 +108,17 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
val intent = Intent() val intent = Intent()
intent.putExtra("File", path) intent.putExtra("File", path)
setResult(RESULT_OK, intent) setResult(RESULT_OK, intent)
// bookmarkManager.save()
finish() finish()
} }
} else if (viewModel.startTypeData == FileManagerViewModel.StartType.SELECT_FILE && requestCode == 2) { } else if (viewModel.startTypeData == FileManagerViewModel.StartType.SELECT_FILE && requestCode == 2) {
val path = viewModel.parseFilePath(this@FileManagerActivity, data) // val path = viewModel.parseFilePath(this@FileManagerActivity, data)
if (path != null) { // if (path != null) {
val intent = Intent() // val intent = Intent()
intent.putExtra("File", path) // intent.putExtra("File", path)
setResult(RESULT_OK, intent) // setResult(RESULT_OK, intent)
// bookmarkManager.save() //// bookmarkManager.save()
finish() // finish()
} // }
} else {
Toast.makeText(this, "未设置的操作", Toast.LENGTH_SHORT).show()
} }
// else if (requestCode == 3) { // else if (requestCode == 3) {
//新建源文件 //新建源文件
@ -509,6 +140,11 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
} }
} }
lateinit var photoAlbumResultLauncher: ActivityResultLauncher<Intent>
lateinit var systemFileManagerResultLauncher: ActivityResultLauncher<String>
// //
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId val id = item.itemId
@ -522,22 +158,22 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
viewModel.loadFiles(viewModel.getCurrentPath()) viewModel.loadFiles(viewModel.getCurrentPath())
return true return true
} }
R.id.photo_album -> { // R.id.photo_album -> {
this@FileManagerActivity.startActivityForResult( // this@FileManagerActivity.startActivityForResult(
Intent( // Intent(
Intent.ACTION_PICK, // Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI // MediaStore.Images.Media.EXTERNAL_CONTENT_URI
), 1 // ), 1
) // )
return true // return true
} // }
R.id.system_file_manager -> { // R.id.system_file_manager -> {
val intent = Intent(Intent.ACTION_GET_CONTENT) // val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*" // intent.type = "*/*"
intent.addCategory(Intent.CATEGORY_OPENABLE) // intent.addCategory(Intent.CATEGORY_OPENABLE)
this@FileManagerActivity.startActivityForResult(intent, 2) // this@FileManagerActivity.startActivityForResult(intent, 2)
return true // return true
} // }
R.id.creteFolder -> { R.id.creteFolder -> {
// createFolderAction() // createFolderAction()
return true return true
@ -550,7 +186,6 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) { return if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) {
if (viewModel.getCurrentPath() == viewModel.getRootPath()) { if (viewModel.getCurrentPath() == viewModel.getRootPath()) {
// bookmarkManager.save()
finish() finish()
true true
} else { } else {
@ -823,16 +458,6 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
// return null // return null
// } // }
// //
// override fun getViewBindingObject(layoutInflater: LayoutInflater): ActivityFileBinding {
// return ActivityFileBinding.inflate(layoutInflater)
// }
//
// override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
// if (canUseView) {
// initView()
// initAction()
// }
// }
private lateinit var menuBinding: MenuBinding private lateinit var menuBinding: MenuBinding
private val viewModel: FileManagerViewModel by lazy { private val viewModel: FileManagerViewModel by lazy {
ViewModelProvider(this).get(FileManagerViewModel::class.java) ViewModelProvider(this).get(FileManagerViewModel::class.java)
@ -882,32 +507,59 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
viewModel.loadFiles(viewModel.getCurrentPath()) viewModel.loadFiles(viewModel.getCurrentPath())
viewBinding.swipeRefreshLayout.isRefreshing = false viewBinding.swipeRefreshLayout.isRefreshing = false
} }
systemFileManagerResultLauncher =
registerForActivityResult(ActivityResultContracts.GetContent()) {
val path = viewModel.parseFilePath(this, it)
if (path != null) {
CoreDialog(this).setTitle(R.string.system_file_manager).setMessage(path)
.setPositiveButton(R.string.select_file) {
setResultAndFinish(path)
}.setNegativeButton(R.string.dialog_cancel) {
}.setCancelable(false).show()
} else {
Snackbar.make(
viewBinding.fab,
R.string.bad_file_type,
Snackbar.LENGTH_SHORT
).show()
}
}
FastScrollerBuilder(viewBinding.recyclerView).useMd2Style() FastScrollerBuilder(viewBinding.recyclerView).useMd2Style()
.setPopupTextProvider(adapter).build() .setPopupTextProvider(adapter).build()
} else { } else {
val bundle = intent.getBundleExtra("data") val bundle = intent.getBundleExtra("data")
if (bundle == null) { if (bundle != null) {
showError("无效的请求。") if (bundle.containsKey("path")) {
finish() viewModel.currentPathLiveData.value = bundle.getString("path")
return }
} if (bundle.containsKey("type")) {
if (bundle.containsKey("path")) { val type = bundle.getString("type")
viewModel.currentPathLiveData.value = bundle.getString("path") viewModel.startTypeData = when (type) {
} "selectDirectents" -> {
if (bundle.containsKey("type")) { Snackbar.make(
val type = bundle.getString("type") viewBinding.fab,
viewModel.startTypeData = when (type) { R.string.select_directents,
"selectDirectents" -> { Snackbar.LENGTH_INDEFINITE
FileManagerViewModel.StartType.SELECT_DIRECTORY ).setAction(R.string.dialog_ok) {
} finish()
else -> { }.setGestureInsetBottomIgnored(true).show()
FileManagerViewModel.StartType.DEFAULT FileManagerViewModel.StartType.SELECT_DIRECTORY
}
"selectFile" -> {
FileManagerViewModel.StartType.SELECT_FILE
}
else -> {
FileManagerViewModel.StartType.DEFAULT
}
} }
} }
if (bundle.containsKey("rootpath")) {
viewModel.setRootPath(bundle.getString("rootpath"))
}
} }
if (bundle.containsKey("rootpath")) {
viewModel.setRootPath(bundle.getString("rootpath"))
}
} }
} }
@ -920,6 +572,10 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
if (viewModel.startTypeData != FileManagerViewModel.StartType.SELECT_FILE) { if (viewModel.startTypeData != FileManagerViewModel.StartType.SELECT_FILE) {
menu.removeItem(R.id.selectFile) menu.removeItem(R.id.selectFile)
} }
menuBinding.systemFileManagerItem.setOnMenuItemClickListener {
systemFileManagerResultLauncher.launch("*/*")
true
}
menuBinding.actionSortByType.setOnMenuItemClickListener { menuBinding.actionSortByType.setOnMenuItemClickListener {
viewModel.sortTypeLiveData.value = FileManagerViewModel.SortType.BY_TYPE viewModel.sortTypeLiveData.value = FileManagerViewModel.SortType.BY_TYPE
true true
@ -964,6 +620,16 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
} }
} }
/**
* 设置结果并结束界面
*/
fun setResultAndFinish(path: String) {
val temIntent = Intent()
temIntent.putExtra("File", path)
setResult(RESULT_OK, temIntent)
finish()
}
/** /**
* 加载观察者 * 加载观察者
@ -989,6 +655,17 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
} else { } else {
if (file.isDirectory) { if (file.isDirectory) {
viewModel.currentPathLiveData.value = file.absolutePath viewModel.currentPathLiveData.value = file.absolutePath
} else {
//文件点击事件
if (viewModel.startTypeData == FileManagerViewModel.StartType.SELECT_FILE) {
Snackbar.make(
viewBinding.fab,
R.string.select_file,
Snackbar.LENGTH_SHORT
).setAction(R.string.dialog_ok) {
setResultAndFinish(file.absolutePath)
}.setGestureInsetBottomIgnored(true).show()
}
} }
} }
} }
@ -1098,8 +775,7 @@ class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
} }
} }
viewModel.currentPathLiveData.observe(this) { viewModel.currentPathLiveData.observe(this) {
if (it==null) if (it == null) {
{
return@observe return@observe
} }
val root = getString(R.string.root_path) val root = getString(R.string.root_path)

View File

@ -19,6 +19,7 @@ class LibraryActivity : BaseActivity<ActivityLibraryBinding>() {
*/ */
private fun getLibInfoList(): ArrayList<LibInfo> { private fun getLibInfoList(): ArrayList<LibInfo> {
val libInfoArrayList = ArrayList<LibInfo>() val libInfoArrayList = ArrayList<LibInfo>()
libInfoArrayList.add( libInfoArrayList.add(
LibInfo( LibInfo(
"Kotlin", "Kotlin",
@ -27,6 +28,22 @@ class LibraryActivity : BaseActivity<ActivityLibraryBinding>() {
"Apache License 2.0" "Apache License 2.0"
) )
) )
// libInfoArrayList.add(
// LibInfo(
// "Light",
// "The usual Snackbar, but elegant",
// "https://github.com/TonnyL/Light",
// "MIT"
// )
// )
libInfoArrayList.add(
LibInfo(
"FloatingActionButtonSpeedDial",
"A Floating Action Button Speed Dial implementation for Android that follows the Material Design specification",
"https://github.com/leinardi/FloatingActionButtonSpeedDial",
"Apache License 2.0"
)
)
libInfoArrayList.add( libInfoArrayList.add(
LibInfo( LibInfo(
"Banner", "Banner",

View File

@ -16,7 +16,10 @@ import androidx.core.view.GravityCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.* import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.coldmint.dialog.CoreDialog import com.coldmint.dialog.CoreDialog
@ -80,12 +83,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
navController.navInflater.inflate(R.navigation.main_nav).apply { navController.navInflater.inflate(R.navigation.main_nav).apply {
val use = val use =
AppSettings.getValue(AppSettings.Setting.UseTheCommunityAsTheLaunchPage, true) AppSettings.getValue(AppSettings.Setting.UseTheCommunityAsTheLaunchPage, true)
startDestination = if (use) { this.setStartDestination(
viewBinding.mainButton.hide() if (use) {
R.id.community_item viewBinding.mainButton.hide()
} else { R.id.community_item
R.id.mod_item } else {
} R.id.mod_item
}
)
navController.graph = this navController.graph = this
} }
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
@ -448,7 +453,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
val compressionManager = CompressionManager.instance val compressionManager = CompressionManager.instance
if (templateDirectory.exists()) { if (templateDirectory.exists()) {
val gson = Gson() val gson = Gson()
val newInfoData = compressionManager.readEntry(formFile, LocalTemplatePackage.INFONAME) val newInfoData =
compressionManager.readEntry(formFile, LocalTemplatePackage.INFONAME)
if (newInfoData == null) { if (newInfoData == null) {
handler.post { handler.post {
Snackbar.make( Snackbar.make(

View File

@ -10,13 +10,13 @@ import com.coldmint.rust.core.tool.LineParser
import com.coldmint.rust.core.interfaces.LineParserEvent import com.coldmint.rust.core.interfaces.LineParserEvent
import android.text.SpannableString import android.text.SpannableString
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
import com.afollestad.materialdialogs.MaterialDialog
import android.text.Spanned import android.text.Spanned
import android.os.Looper import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.coldmint.dialog.CoreDialog
import com.coldmint.rust.core.tool.FileOperator import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.pro.adapters.OptimizeAdapter import com.coldmint.rust.pro.adapters.OptimizeAdapter
import com.coldmint.rust.pro.databean.OptimizeGroup import com.coldmint.rust.pro.databean.OptimizeGroup
@ -173,7 +173,7 @@ class OptimizeActivity : BaseActivity<ActivityOptimizeBinding>() {
* @param file * @param file
*/ */
private fun analyzeFile(file: File) { private fun analyzeFile(file: File) {
if (mFileSignatureCache!!.isChange(file)) { if (mFileSignatureCache.isChange(file)) {
hasError = false hasError = false
val type = FileOperator.getFileType(file) val type = FileOperator.getFileType(file)
when (type) { when (type) {
@ -237,22 +237,11 @@ class OptimizeActivity : BaseActivity<ActivityOptimizeBinding>() {
spannableString.setSpan( spannableString.setSpan(
object : ClickableSpan() { object : ClickableSpan() {
override fun onClick(widget: View) { override fun onClick(widget: View) {
val materialDialog = MaterialDialog( CoreDialog(this@OptimizeActivity).setTitle(R.string.details)
this@OptimizeActivity, .setMessage(lineBuilder.toString())
MaterialDialog.DEFAULT_BEHAVIOR .setPositiveButton(R.string.close) {
)
materialDialog.title(R.string.details, null) }.show()
materialDialog.message(
null,
lineBuilder.toString(),
null
)
materialDialog.positiveButton(
R.string.close,
null,
null
)
materialDialog.show()
} }
}, },
tip.indexOf(action), tip.indexOf(action),
@ -278,41 +267,25 @@ class OptimizeActivity : BaseActivity<ActivityOptimizeBinding>() {
spannableString.setSpan( spannableString.setSpan(
object : ClickableSpan() { object : ClickableSpan() {
override fun onClick(widget: View) { override fun onClick(widget: View) {
val materialDialog = MaterialDialog( CoreDialog(this@OptimizeActivity).setTitle(R.string.details)
this@OptimizeActivity, .setMessage(noteBuilder.toString())
MaterialDialog.DEFAULT_BEHAVIOR .setPositiveButton(R.string.edit) {
) val bundle = Bundle()
materialDialog.title(R.string.details, null) bundle.putString("path", file.absolutePath)
materialDialog.message( bundle.putString(
null, "modPath",
noteBuilder.toString(), FileOperator.getSuperDirectory(file)
null
)
materialDialog.negativeButton(
R.string.edit,
null
) { materialDialog: MaterialDialog? ->
val bundle = Bundle()
bundle.putString("path", file.absolutePath)
bundle.putString(
"modPath",
FileOperator.getSuperDirectory(file)
)
val intent =
Intent(
this@OptimizeActivity,
EditActivity::class.java
) )
intent.putExtra("data", bundle) val intent =
this@OptimizeActivity.startActivity(intent) Intent(
null this@OptimizeActivity,
} EditActivity::class.java
materialDialog.positiveButton( )
R.string.close, intent.putExtra("data", bundle)
null, this@OptimizeActivity.startActivity(intent)
null }.setNegativeButton(R.string.close) {
)
materialDialog.show() }.show()
} }
}, },
tip.indexOf(action), tip.indexOf(action),
@ -342,7 +315,7 @@ class OptimizeActivity : BaseActivity<ActivityOptimizeBinding>() {
} }
} }
if (!hasError) { if (!hasError) {
mFileSignatureCache!!.putFile(file) mFileSignatureCache.putFile(file)
} }
} }
} }

View File

@ -79,7 +79,7 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) { override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) { if (canUseView) {
viewBinding.toolbar.title = getText(R.string.release) title = getText(R.string.release)
setReturnButton() setReturnButton()
val layoutManager = LinearLayoutManager(this) val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = RecyclerView.HORIZONTAL layoutManager.orientation = RecyclerView.HORIZONTAL
@ -876,7 +876,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
apiCallBack = object : ApiCallBack<ApiResponse> { apiCallBack = object : ApiCallBack<ApiResponse> {
override fun onResponse(t: ApiResponse) { override fun onResponse(t: ApiResponse) {
dialog.dismiss() dialog.dismiss()
resetButton()
if (t.code == ServerConfiguration.Success_Code) { if (t.code == ServerConfiguration.Success_Code) {
val temModClass = modClass val temModClass = modClass
if (temModClass != null) { if (temModClass != null) {
@ -922,7 +921,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
override fun onFailure(e: Exception) { override fun onFailure(e: Exception) {
dialog.dismiss() dialog.dismiss()
showInternetError(viewBinding.releaseButton, e) showInternetError(viewBinding.releaseButton, e)
resetButton()
} }
}, progressListener = object : ProgressListener { }, progressListener = object : ProgressListener {
@ -944,13 +942,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
} }
}) })
viewBinding.releaseButton.text = getString(R.string.releaseing)
viewBinding.releaseButton.setBackgroundColor(
GlobalMethod.getThemeColor(
this,
R.attr.colorPrimaryVariant
)
)
} }
@ -989,7 +980,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
apiCallBack = object : ApiCallBack<ApiResponse> { apiCallBack = object : ApiCallBack<ApiResponse> {
override fun onResponse(t: ApiResponse) { override fun onResponse(t: ApiResponse) {
dialog.dismiss() dialog.dismiss()
resetButton()
if (t.code == ServerConfiguration.Success_Code) { if (t.code == ServerConfiguration.Success_Code) {
val temModClass = modClass val temModClass = modClass
if (temModClass != null) { if (temModClass != null) {
@ -1040,7 +1030,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
override fun onFailure(e: Exception) { override fun onFailure(e: Exception) {
dialog.dismiss() dialog.dismiss()
showInternetError(viewBinding.releaseButton, e) showInternetError(viewBinding.releaseButton, e)
resetButton()
} }
}, progressListener = object : ProgressListener { }, progressListener = object : ProgressListener {
@ -1062,13 +1051,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
} }
}) })
viewBinding.releaseButton.text = getString(R.string.releaseing)
viewBinding.releaseButton.setBackgroundColor(
GlobalMethod.getThemeColor(
this,
R.attr.colorPrimaryVariant
)
)
} }
/** /**
@ -1120,15 +1102,6 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
} }
} }
/**
* 重新设置按钮
*/
fun resetButton() {
viewBinding.releaseButton.text = getString(R.string.release)
viewBinding.releaseButton.setBackgroundColor(
GlobalMethod.getColorPrimary(this)
)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View File

@ -7,6 +7,7 @@ import android.util.Log
import cat.ereza.customactivityoncrash.config.CaocConfig import cat.ereza.customactivityoncrash.config.CaocConfig
import com.coldmint.rust.core.web.ServerConfiguration import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.pro.tool.AppSettings import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.CompletionItemConverter
import com.coldmint.rust.pro.tool.GlobalMethod import com.coldmint.rust.pro.tool.GlobalMethod
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import com.google.android.material.color.DynamicColorsOptions import com.google.android.material.color.DynamicColorsOptions
@ -28,6 +29,7 @@ class RustApplication : Application() {
DynamicColors.isDynamicColorAvailable() DynamicColors.isDynamicColorAvailable()
) )
}.build() }.build()
CompletionItemConverter.init(this)
DynamicColors.applyToActivitiesIfAvailable(this, options) DynamicColors.applyToActivitiesIfAvailable(this, options)
//程序崩溃 //程序崩溃
CaocConfig.Builder.create() CaocConfig.Builder.create()

View File

@ -51,6 +51,13 @@ class SettingsActivity : BaseActivity<ActivitySettingsBinding>() {
val english_editing_mode = val english_editing_mode =
manager.findPreference<SwitchPreference>(requireContext().getString(R.string.setting_english_editing_mode)) manager.findPreference<SwitchPreference>(requireContext().getString(R.string.setting_english_editing_mode))
val customizeEdit = manager.findPreference<PreferenceScreen>("customize_edit")
customizeEdit!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val intent = Intent(requireContext(), CustomizeEditTextActivity::class.java)
startActivity(intent)
true
}
val dynamicColor = val dynamicColor =
manager.findPreference<SwitchPreference>(requireContext().getString(R.string.setting_dynamic_color)) manager.findPreference<SwitchPreference>(requireContext().getString(R.string.setting_dynamic_color))
if (!DynamicColors.isDynamicColorAvailable()) { if (!DynamicColors.isDynamicColorAvailable()) {
@ -147,12 +154,12 @@ class SettingsActivity : BaseActivity<ActivitySettingsBinding>() {
val nightMode: SwitchPreference? = val nightMode: SwitchPreference? =
manager.findPreference<SwitchPreference>(getString(R.string.setting_night_mode)) manager.findPreference<SwitchPreference>(getString(R.string.setting_night_mode))
nightMode?.setOnPreferenceChangeListener { preference, newValue -> nightMode?.setOnPreferenceChangeListener { preference, newValue ->
val booleanValue = newValue as Boolean val booleanValue = newValue as Boolean
if (booleanValue) { if (booleanValue) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} else { } else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
} }
true true
} }

View File

@ -9,10 +9,12 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.widget.Toast
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.coldmint.rust.core.ModClass import com.coldmint.rust.core.ModClass
import com.coldmint.rust.core.SourceFile import com.coldmint.rust.core.SourceFile
import com.coldmint.rust.core.turret.TurretInstaller import com.coldmint.rust.core.turret.TurretInstaller
import com.coldmint.rust.core.turret.TurretSketchpadView
import com.coldmint.rust.pro.base.BaseActivity import com.coldmint.rust.pro.base.BaseActivity
import com.coldmint.rust.pro.databinding.ActivityTurretDesignBinding import com.coldmint.rust.pro.databinding.ActivityTurretDesignBinding
import java.io.File import java.io.File
@ -22,9 +24,6 @@ import java.io.File
*/ */
class TurretDesignActivity : BaseActivity<ActivityTurretDesignBinding>() { class TurretDesignActivity : BaseActivity<ActivityTurretDesignBinding>() {
lateinit var turretInstaller: TurretInstaller
val scale = 5
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) { override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) { if (canUseView) {
@ -51,18 +50,25 @@ class TurretDesignActivity : BaseActivity<ActivityTurretDesignBinding>() {
return return
} else { } else {
val file = mainImage[0] val file = mainImage[0]
val bitmap = BitmapFactory.decodeFile(file.absolutePath) viewBinding.turretSketchpadView.setImage(file.absolutePath)
viewBinding.mainImageView.setImageBitmap(bitmap) // viewBinding.toolbar.postDelayed({
val layoutParams = viewBinding.mainImageView.layoutParams // Toast.makeText(this, "执行", Toast.LENGTH_SHORT).show()
layoutParams.width = bitmap.width * scale // viewBinding.turretsDragView.setBaseImage(file.absolutePath)
layoutParams.height = bitmap.height * scale // }, 1000)
// val bitmap = BitmapFactory.decodeFile(file.absolutePath)
// viewBinding.mainImageView.setImageBitmap(bitmap)
// val layoutParams = viewBinding.mainImageView.layoutParams
// layoutParams.width = bitmap.width * scale
// layoutParams.height = bitmap.height * scale
} }
// val sketchpadView = TurretSketchpadView(this)
turretInstaller = // sketchpadView.
TurretInstaller(viewBinding.relativeLayout, sourceFile) // viewBinding.frameLayout.addView(sketchpadView)
turretInstaller.setScale(scale) TurretInstaller.installerAllTurret(viewBinding.frameLayout, sourceFile) {
turretInstaller.installAllTurrets() val game = viewBinding.turretSketchpadView.toGameCoordinate(it)
// viewBinding.textView.text = "坐标 x:${game.x} y:${game.y}"
}
} }
} }

View File

@ -18,6 +18,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.coldmint.dialog.CoreDialog
import com.coldmint.rust.pro.R import com.coldmint.rust.pro.R
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
@ -121,12 +122,8 @@ abstract class BaseActivity<ViewBingType : ViewBinding> :
* @param msg String 错误信息 * @param msg String 错误信息
*/ */
protected fun showError(msg: String) { protected fun showError(msg: String) {
MaterialDialog(this).show { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
title(R.string.error).message(text = msg).cancelable(false) finish()
.positiveButton(R.string.dialog_close) {
finish()
}
}
} }
/** /**
@ -155,10 +152,10 @@ abstract class BaseActivity<ViewBingType : ViewBinding> :
"${msg}\n${exception}" "${msg}\n${exception}"
} }
if (view == null) { if (view == null) {
MaterialDialog(this).show { CoreDialog(this).setTitle(R.string.details).setMessage(thisMsg)
title(R.string.details).message(text = thisMsg) .setPositiveButton(R.string.dialog_ok) {
.positiveButton(R.string.dialog_ok)
} }.show()
} else { } else {
Snackbar.make( Snackbar.make(
view, view,

View File

@ -49,11 +49,11 @@ class RustAnalyzer() : EnglishMode {
/** /**
* 语法分析器 // * 语法分析器
* @param content CharSequence // * @param content CharSequence
* @param colors TextAnalyzeResult // * @param colors TextAnalyzeResult
* @param delegate Delegate // * @param delegate Delegate
*/ // */
// override fun analyze( // override fun analyze(
// content: CharSequence, // content: CharSequence,
// colors: TextAnalyzeResult, // colors: TextAnalyzeResult,

View File

@ -19,14 +19,15 @@ import java.util.ArrayList
import java.util.concurrent.Executors import java.util.concurrent.Executors
/** /**
*
* @author Cold Mint * @author Cold Mint
* @date 2022/1/25 17:32 * @date 2022/1/25 17:32
*/ */
@Deprecated("")
class RustAutoComplete(val context: Context) : EnglishMode { class RustAutoComplete(val context: Context) : EnglishMode {
private val debugKey = "自动完成器" private val debugKey = "自动完成器"
private var codeDataBase: CodeDataBase? = null private var codeDataBase: CodeDataBase? = null
private val executorService = Executors.newCachedThreadPool()
private var fileDataBase: FileDataBase? = null private var fileDataBase: FileDataBase? = null
private var codeEditor: CodeEditor? = null private var codeEditor: CodeEditor? = null
@ -41,16 +42,8 @@ class RustAutoComplete(val context: Context) : EnglishMode {
AppSettings.getValue(AppSettings.Setting.IdentifiersPromptNumber, 40) AppSettings.getValue(AppSettings.Setting.IdentifiersPromptNumber, 40)
} }
//类型转换器
private val completionItemConverter: CompletionItemConverter by lazy {
CompletionItemConverter.instance.init(context)
}
companion object {
var keyWord = ""
}
/** /**
* 是否为英文模式 * 是否为英文模式
*/ */
@ -62,7 +55,7 @@ class RustAutoComplete(val context: Context) : EnglishMode {
*/ */
fun setSourceFolder(sourceFolder: String) { fun setSourceFolder(sourceFolder: String) {
DebugHelper.printLog(debugKey, "已设置源文件目录" + sourceFolder, "设置源文件目录") DebugHelper.printLog(debugKey, "已设置源文件目录" + sourceFolder, "设置源文件目录")
completionItemConverter.setSourceFilePath(sourceFolder) CompletionItemConverter.setSourceFilePath(sourceFolder)
} }
/** /**
@ -76,7 +69,7 @@ class RustAutoComplete(val context: Context) : EnglishMode {
rootCodeName: String, rootCodeName: String,
modFolder: String modFolder: String
) { ) {
completionItemConverter.configurationFileConversion(sourceFilePath, rootCodeName, modFolder) CompletionItemConverter.configurationFileConversion(sourceFilePath, rootCodeName, modFolder)
} }
/** /**
@ -149,277 +142,276 @@ class RustAutoComplete(val context: Context) : EnglishMode {
return return
} }
keyWord = prefix // val temCodeEditor: CodeEditor = codeEditor!!
val temCodeEditor: CodeEditor = codeEditor!! // val lineData = temCodeEditor.text.getLineString(line)
val lineData = temCodeEditor.text.getLineString(line) // if (lineData.startsWith('[')) {
if (lineData.startsWith('[')) { // //搜索节
//搜索节 // val name = lineData.subSequence(1, lineData.length).toString()
val name = lineData.subSequence(1, lineData.length).toString() // val list = if (isEnglishMode) {
val list = if (isEnglishMode) { // codeDataBase!!.getSectionDao()
codeDataBase!!.getSectionDao() // .searchSectionInfoByCode(name, limitNum = identifiersPromptNumber)
.searchSectionInfoByCode(name, limitNum = identifiersPromptNumber) // } else {
} else { // codeDataBase!!.getSectionDao()
codeDataBase!!.getSectionDao() // .searchSectionInfoByTranslate(name, limitNum = identifiersPromptNumber)
.searchSectionInfoByTranslate(name, limitNum = identifiersPromptNumber) // }
} // list?.forEach {
list?.forEach { // completionPublisher.addItem(CompletionItemConverter.sectionInfoToCompletionItem(it))
completionPublisher.addItem(completionItemConverter.sectionInfoToCompletionItem(it)) // }
} // } else {
} else { // val key = ":"
val key = ":" // val keyIndex = lineData.lastIndexOf(key)
val keyIndex = lineData.lastIndexOf(key) // if (keyIndex > -1) {
if (keyIndex > -1) { // //检查是否可响应变量
//检查是否可响应变量 // val start = "\${"
val start = "\${" // val end = "}"
val end = "}" // val startIndex = lineData.lastIndexOf(start)
val startIndex = lineData.lastIndexOf(start) // if (startIndex > -1) {
if (startIndex > -1) { // val endIndex = lineData.lastIndexOf(end)
val endIndex = lineData.lastIndexOf(end) // if (endIndex < startIndex) {
if (endIndex < startIndex) { // //如果}的位置小于${的位置,说明没有闭合
//如果}的位置小于${的位置,说明没有闭合 // val keyWord =
val keyWord = // lineData.subSequence(startIndex + start.length, lineData.length)
lineData.subSequence(startIndex + start.length, lineData.length) // .toString()
.toString() // val previousText =
val previousText = // lineData.subSequence(keyIndex + key.length, startIndex).toString()
lineData.subSequence(keyIndex + key.length, startIndex).toString() // if (keyWord.isNotBlank()) {
if (keyWord.isNotBlank()) { // RustAnalyzer.localVariableNameList.forEach {
RustAnalyzer.localVariableNameList.forEach { // if (it.name.contains(keyWord)) {
if (it.name.contains(keyWord)) { // completionPublisher.addItem(
completionPublisher.addItem( // CompletionItemConverter.localVariableNameToCompletionItem(
completionItemConverter.localVariableNameToCompletionItem( // it, previousText
it, previousText
)
)
}
}
} else {
RustAnalyzer.localVariableNameList.forEach {
completionPublisher.addItem(
completionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
RustAutoComplete.keyWord = keyWord
return
}
}
// val value =
// lineData.subSequence(keyIndex + key.length, lineData.length).toString().trim()
// Log.d("值", value)
//搜索值
// frontIndex 前面冒号的位置
val frontIndex = lineData.lastIndexOf(key, keyIndex - key.length)
val keyValue = if (frontIndex > -1) {
lineData.subSequence(frontIndex + key.length, keyIndex)
} else {
lineData.subSequence(0, keyIndex)
}
val codeInfo =
if (isEnglishMode) {
codeDataBase!!.getCodeDao().findCodeByCode(keyValue.toString())
} else {
codeDataBase!!.getCodeDao().findCodeByTranslate(keyValue.toString())
}
DebugHelper.printLog(
debugKey,
"值[" + keyValue + "]英文模式[" + isEnglishMode + "]代码信息[" + codeInfo + "]关键字[" + prefix + "]",
"值检查"
)
if (codeInfo != null) {
val typeInfo = completionItemConverter.getValueType(codeInfo.type)
//获取代码的关联列表
if (typeInfo != null && typeInfo.list.isNotBlank()) {
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]自动提示列表[" + typeInfo.list + "]", "关联提示"
)
lineParser.text = typeInfo.list
lineParser.analyse { lineNum, lineData, isEnd ->
//分析关联提示项目
val temCodeInfo =
codeDataBase!!.getCodeDao().findCodeByCode(lineData)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是代码[" + (temCodeInfo != null) + "]",
"关联提示列表分析"
)
if (temCodeInfo == null) {
if (lineData.startsWith("@file(") && lineData.endsWith(")")) {
val fileType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
)
val fileInfo = fileDataBase!!.getFileInfoDao()
.searchFileInfoByNameAndType(
prefix,
fileType.toString(),
identifiersPromptNumber
)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]搜索了[" + fileType + "]类型的文件,返回了[" + (fileInfo?.size
?: -1) + "]个结果",
"关联提示列表分析"
)
if (fileInfo != null && fileInfo.isNotEmpty()) {
for (fileTable in fileInfo) {
completionPublisher.addItem(
completionItemConverter.fileTableToCompletionItem(
fileTable
)
)
}
}
} else if (lineData.startsWith("@customType(") && lineData.endsWith(
")"
)
) {
//用户自动值类型提示
val customType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
fileDataBase!!.getValueDao()
.searchValueByKey(
prefix,
customType,
identifiersPromptNumber
)
?.forEach {
completionPublisher.addItem(
completionItemConverter.valueTableToCompletionItem(
it
)
)
}
} else if (lineData.startsWith("@type(") && lineData.endsWith(")")) {
val type = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
val list = if (isEnglishMode
) {
codeDataBase!!.getCodeDao().findCodeByCodeInType(
prefix,
type,
identifiersPromptNumber
)
} else {
codeDataBase!!.getCodeDao().findCodeByTranslateInType(
prefix,
type,
identifiersPromptNumber
)
}
DebugHelper.printLog(
debugKey,
"关联了值类型[" + type + "]获取[" + (list?.size ?: -1) + "]个结果",
"值类型引用"
)
if (!list.isNullOrEmpty()) {
list.forEach {
completionPublisher.addItem(
completionItemConverter.codeInfoToCompletionItem(
it
)
)
}
}
} else if (lineData.startsWith("@section") && lineData.endsWith(
")"
)
) {
val section = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
// codeEditor!!.textAnalyzeResult.navigation.forEach {
// if (section == getSectionType(it.label)) {
// result.add(
// completionItemConverter.navigationItemToCompletionItem(
// it
// )
// )
// }
// }
} else {
//无法分析的关联项目
// result.add(
// CompletionItem(
// lineData,
// String.format(
// completionItemConverter.associatedTip,
// codeInfo.translate
// )
// )
// ) // )
} // )
} else { // }
// }
val show = if (isEnglishMode) { // } else {
temCodeInfo.code.contains(prefix) // RustAnalyzer.localVariableNameList.forEach {
} else { // completionPublisher.addItem(
temCodeInfo.translate.contains(prefix) // CompletionItemConverter.localVariableNameToCompletionItem(
} // it, previousText
DebugHelper.printLog( // )
debugKey, // )
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是否包含" + prefix + "关键字[" + show + "]",
"关联提示列表分析"
)
if (show) {
completionPublisher.addItem(
completionItemConverter.codeInfoToCompletionItem(
temCodeInfo
)
)
}
}
true
}
}
}
} else {
//如果不包含:搜索键
// val navigationList = temCodeEditor.textAnalyzeResult.navigation
// var section: String? = null
// if (navigationList != null && navigationList.isNotEmpty()) {
// for (navigation in navigationList) {
// if (navigation.line > line) {
// break
// } else {
// section = navigation.label
// } // }
// } // }
// RustAutoComplete.keyWord = keyWord
// return
// } // }
// //如果不在任何节内 // }
// if (section == null) { //
// return@submit //// val value =
// } //// lineData.subSequence(keyIndex + key.length, lineData.length).toString().trim()
// val trueSection = getSectionType(section) //// Log.d("值", value)
// val list = if (isEnglishMode) { // //搜索值
// codeDataBase!!.getCodeDao().findCodeByEnglishCodeKeyFromSection( // // frontIndex 前面冒号的位置
// prefix, // val frontIndex = lineData.lastIndexOf(key, keyIndex - key.length)
// trueSection, // val keyValue = if (frontIndex > -1) {
// identifiersPromptNumber // lineData.subSequence(frontIndex + key.length, keyIndex)
// ) // } else {
// lineData.subSequence(0, keyIndex)
// }
//
// val codeInfo =
// if (isEnglishMode) {
// codeDataBase!!.getCodeDao().findCodeByCode(keyValue.toString())
// } else { // } else {
// codeDataBase!!.getCodeDao() // codeDataBase!!.getCodeDao().findCodeByTranslate(keyValue.toString())
// .findCodeByKeyFromSection(prefix, trueSection, identifiersPromptNumber)
// } // }
// if (list != null && list.isNotEmpty()) { // DebugHelper.printLog(
// list.forEach { // debugKey,
// result.add( // "值[" + keyValue + "]英文模式[" + isEnglishMode + "]代码信息[" + codeInfo + "]关键字[" + prefix + "]",
// completionItemConverter.codeInfoToCompletionItem(it) // "值检查"
// )
// if (codeInfo != null) {
// val typeInfo = CompletionItemConverter.getValueType(codeInfo.type)
// //获取代码的关联列表
// if (typeInfo != null && typeInfo.list.isNotBlank()) {
// DebugHelper.printLog(
// debugKey,
// "值类型[" + codeInfo.type + "]自动提示列表[" + typeInfo.list + "]", "关联提示"
// )
// lineParser.text = typeInfo.list
// lineParser.analyse { lineNum, lineData, isEnd ->
// //分析关联提示项目
// val temCodeInfo =
// codeDataBase!!.getCodeDao().findCodeByCode(lineData)
// DebugHelper.printLog(
// debugKey,
// "值类型[" + codeInfo.type + "]项目[" + lineData + "]是代码[" + (temCodeInfo != null) + "]",
// "关联提示列表分析"
// ) // )
// if (temCodeInfo == null) {
// if (lineData.startsWith("@file(") && lineData.endsWith(")")) {
// val fileType = lineData.subSequence(
// lineData.indexOf('(') + 1,
// lineData.indexOf(')')
// )
//
// val fileInfo = fileDataBase!!.getFileInfoDao()
// .searchFileInfoByNameAndType(
// prefix,
// fileType.toString(),
// identifiersPromptNumber
// )
// DebugHelper.printLog(
// debugKey,
// "值类型[" + codeInfo.type + "]项目[" + lineData + "]搜索了[" + fileType + "]类型的文件,返回了[" + (fileInfo?.size
// ?: -1) + "]个结果",
// "关联提示列表分析"
// )
// if (fileInfo != null && fileInfo.isNotEmpty()) {
// for (fileTable in fileInfo) {
// completionPublisher.addItem(
// CompletionItemConverter.fileTableToCompletionItem(
// fileTable
// )
// )
// }
// }
// } else if (lineData.startsWith("@customType(") && lineData.endsWith(
// ")"
// )
// ) {
// //用户自动值类型提示
// val customType = lineData.subSequence(
// lineData.indexOf('(') + 1,
// lineData.indexOf(')')
// ).toString()
// fileDataBase!!.getValueDao()
// .searchValueByKey(
// prefix,
// customType,
// identifiersPromptNumber
// )
// ?.forEach {
// completionPublisher.addItem(
// CompletionItemConverter.valueTableToCompletionItem(
// it
// )
// )
// }
// } else if (lineData.startsWith("@type(") && lineData.endsWith(")")) {
// val type = lineData.subSequence(
// lineData.indexOf('(') + 1,
// lineData.indexOf(')')
// ).toString()
// val list = if (isEnglishMode
// ) {
// codeDataBase!!.getCodeDao().findCodeByCodeInType(
// prefix,
// type,
// identifiersPromptNumber
// )
// } else {
// codeDataBase!!.getCodeDao().findCodeByTranslateInType(
// prefix,
// type,
// identifiersPromptNumber
// )
// }
// DebugHelper.printLog(
// debugKey,
// "关联了值类型[" + type + "]获取[" + (list?.size ?: -1) + "]个结果",
// "值类型引用"
// )
// if (!list.isNullOrEmpty()) {
// list.forEach {
// completionPublisher.addItem(
// CompletionItemConverter.codeInfoToCompletionItem(
// it
// )
// )
// }
// }
// } else if (lineData.startsWith("@section") && lineData.endsWith(
// ")"
// )
// ) {
// val section = lineData.subSequence(
// lineData.indexOf('(') + 1,
// lineData.indexOf(')')
// ).toString()
//// codeEditor!!.textAnalyzeResult.navigation.forEach {
//// if (section == getSectionType(it.label)) {
//// result.add(
//// CompletionItemConverter.navigationItemToCompletionItem(
//// it
//// )
//// )
//// }
//// }
// } else {
// //无法分析的关联项目
//// result.add(
//// CompletionItem(
//// lineData,
//// String.format(
//// CompletionItemConverter.associatedTip,
//// codeInfo.translate
//// )
//// )
//// )
// }
// } else {
//
// val show = if (isEnglishMode) {
// temCodeInfo.code.contains(prefix)
// } else {
// temCodeInfo.translate.contains(prefix)
// }
// DebugHelper.printLog(
// debugKey,
// "值类型[" + codeInfo.type + "]项目[" + lineData + "]是否包含" + prefix + "关键字[" + show + "]",
// "关联提示列表分析"
// )
// if (show) {
// completionPublisher.addItem(
// CompletionItemConverter.codeInfoToCompletionItem(
// temCodeInfo
// )
// )
// }
// }
// true
// } // }
// } // }
} // }
} // } else {
// //如果不包含:搜索键
//// val navigationList = temCodeEditor.textAnalyzeResult.navigation
//// var section: String? = null
//// if (navigationList != null && navigationList.isNotEmpty()) {
//// for (navigation in navigationList) {
//// if (navigation.line > line) {
//// break
//// } else {
//// section = navigation.label
//// }
//// }
//// }
//// //如果不在任何节内
//// if (section == null) {
//// return@submit
//// }
//// val trueSection = getSectionType(section)
//// val list = if (isEnglishMode) {
//// codeDataBase!!.getCodeDao().findCodeByEnglishCodeKeyFromSection(
//// prefix,
//// trueSection,
//// identifiersPromptNumber
//// )
//// } else {
//// codeDataBase!!.getCodeDao()
//// .findCodeByKeyFromSection(prefix, trueSection, identifiersPromptNumber)
//// }
//// if (list != null && list.isNotEmpty()) {
//// list.forEach {
//// result.add(
//// CompletionItemConverter.codeInfoToCompletionItem(it)
//// )
//// }
//// }
// }
// }
} }
override fun isEnglishMode(): Boolean { override fun isEnglishMode(): Boolean {
@ -428,6 +420,5 @@ class RustAutoComplete(val context: Context) : EnglishMode {
override fun setEnglish(englishMode: Boolean) { override fun setEnglish(englishMode: Boolean) {
this.isEnglishMode = englishMode this.isEnglishMode = englishMode
completionItemConverter.setEnglish(englishMode)
} }
} }

View File

@ -0,0 +1,93 @@
package com.coldmint.rust.pro.edit
import android.os.Bundle
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.pro.edit.autoComplete.AutoCompleteJob
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
import io.github.rosemoe.sora.text.CharPosition
import io.github.rosemoe.sora.text.ContentReference
/**
* 自动完成信息提供者
*/
class RustAutoCompleteProvider {
private val key = "自动完成提供者"
private val jobList = ArrayList<AutoCompleteJob>()
companion object{
var keyWord = ""
}
/**
* 添加任务
* @param job AutoCompleteJob
*/
fun addJob(job: AutoCompleteJob): AutoCompleteJob {
jobList.add(job)
DebugHelper.printLog(key, "添加了新任务${job.getName()}")
return job
}
/**
* 移除任务
*/
fun removeJob(job: AutoCompleteJob): AutoCompleteJob {
jobList.remove(job)
DebugHelper.printLog(key, "移除了任务${job.getName()}")
return job
}
/**
* 请求自动完成
* @param contentReference ContentReference
* @param charPosition CharPosition
* @param completionPublisher CompletionPublisher
* @param bundle Bundle
*/
fun requireAutoComplete(
contentReference: ContentReference,
charPosition: CharPosition,
completionPublisher: CompletionPublisher,
bundle: Bundle
) {
val requireKey = "请求自动完成"
if (jobList.isEmpty()) {
DebugHelper.printLog(key, "没有任务可执行。", requireKey, true)
} else {
//行内容
val lineData = contentReference.getLine(charPosition.getLine())
if (lineData.isBlank()) {
DebugHelper.printLog(requireKey, "行内容为空,无需提示。")
return
}
//光标前内容
val cursorPrefix = lineData.subSequence(0, charPosition.getColumn()).toString()
val symbolIndex = cursorPrefix.lastIndexOf(':')
keyWord = if (symbolIndex > 0) {
//有冒号
cursorPrefix.substring(symbolIndex + 1)
} else {
//无
cursorPrefix
}
var executeNumber = 0
jobList.forEach {
//如果需要执行
if (it.needPerform(contentReference, charPosition)) {
executeNumber++
it.requireAutoComplete(
contentReference,
charPosition,
completionPublisher,
lineData, keyWord
)
}
}
DebugHelper.printLog(key, "执行了${executeNumber}个任务。", requireKey)
}
}
}

View File

@ -42,18 +42,18 @@ class RustCompletionAdapter : EditorCompletionAdapter() {
val editItem = EditItemBinding.inflate(layoutInflater, parent, false) val editItem = EditItemBinding.inflate(layoutInflater, parent, false)
val completionItem = getItem(position) as RustCompletionItem val completionItem = getItem(position) as RustCompletionItem
spannableStringBuilder.clear() spannableStringBuilder.clear()
val label = completionItem.label.toString() val label = completionItem.title
spannableStringBuilder.append(label) spannableStringBuilder.append(label)
//节补丁 //节补丁
if (RustAutoComplete.keyWord.startsWith('[') && RustAutoComplete.keyWord.length > 1) { if (RustAutoCompleteProvider.keyWord.startsWith('[') && RustAutoCompleteProvider.keyWord.length > 1) {
RustAutoComplete.keyWord = RustAutoCompleteProvider.keyWord =
RustAutoComplete.keyWord.subSequence(1, RustAutoComplete.keyWord.length) RustAutoCompleteProvider.keyWord.subSequence(1, RustAutoCompleteProvider.keyWord.length)
.toString() .toString()
} }
val start = label.lowercase(Locale.getDefault()) val start = label.lowercase(Locale.getDefault())
.indexOf(RustAutoComplete.keyWord.lowercase(Locale.getDefault())) .indexOf(RustAutoCompleteProvider.keyWord.lowercase(Locale.getDefault()))
if (start > -1) { if (start > -1) {
val end = start + RustAutoComplete.keyWord.length val end = start + RustAutoCompleteProvider.keyWord.length
spannableStringBuilder.setSpan( spannableStringBuilder.setSpan(
colorSpan, colorSpan,
start, start,

View File

@ -48,7 +48,16 @@ class RustCompletionItem(var title: String) : CompletionItem(title) {
* @param p2 Int * @param p2 Int
* @param p3 Int * @param p3 Int
*/ */
override fun performCompletion(p0: CodeEditor?, p1: Content?, p2: Int, p3: Int) { //CodeEditor editor, Content text, int line, int column
override fun performCompletion(editor: CodeEditor, text: Content, line: Int, column: Int) {
if (label == null) {
return
}
val keyOffset = RustAutoCompleteProvider.keyWord.length
if (keyOffset == 0) {
text.insert(line, column, label)
} else {
text.replace(line, column - keyOffset, line, column, label)
}
} }
} }

View File

@ -90,7 +90,7 @@ class RustIncrementalAnalyzeManager :
spans.add( spans.add(
Span.obtain( Span.obtain(
it.offset, it.offset,
TextStyle.makeStyle(EditorColorScheme.COMMENT) TextStyle.makeStyle(EditorColorScheme.TEXT_NORMAL)
) )
) )
} }
@ -98,7 +98,7 @@ class RustIncrementalAnalyzeManager :
spans.add( spans.add(
Span.obtain( Span.obtain(
it.offset, it.offset,
TextStyle.makeStyle(EditorColorScheme.COMMENT) TextStyle.makeStyle(EditorColorScheme.TEXT_NORMAL)
) )
) )
} }

View File

@ -7,6 +7,7 @@ import com.coldmint.rust.core.database.code.CodeDataBase
import com.coldmint.rust.core.database.file.FileDataBase import com.coldmint.rust.core.database.file.FileDataBase
import com.coldmint.rust.core.interfaces.EnglishMode import com.coldmint.rust.core.interfaces.EnglishMode
import com.coldmint.rust.core.tool.DebugHelper import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.pro.edit.autoComplete.CodeAutoCompleteJob
import io.github.rosemoe.sora.lang.Language import io.github.rosemoe.sora.lang.Language
import io.github.rosemoe.sora.lang.analysis.AnalyzeManager import io.github.rosemoe.sora.lang.analysis.AnalyzeManager
import io.github.rosemoe.sora.lang.completion.CompletionPublisher import io.github.rosemoe.sora.lang.completion.CompletionPublisher
@ -20,23 +21,51 @@ import io.github.rosemoe.sora.text.ContentReference
import io.github.rosemoe.sora.text.TextRange import io.github.rosemoe.sora.text.TextRange
import io.github.rosemoe.sora.widget.CodeEditor import io.github.rosemoe.sora.widget.CodeEditor
import io.github.rosemoe.sora.widget.SymbolPairMatch import io.github.rosemoe.sora.widget.SymbolPairMatch
import java.util.*
class RustLanguage( class RustLanguage() : Language, EnglishMode {
private val context: Context,
) : Language, EnglishMode {
private val mRustAnalyzer: RustAnalyzer by lazy {
RustAnalyzer()
}
private val autoComplete by lazy {
RustAutoComplete(context)
}
// private val autoComplete: RustAutoComplete = RustAutoComplete(context)
private var isEnglishMode = false private var isEnglishMode = false
private val rustAnalyzeManager by lazy { private val rustAnalyzeManager by lazy {
RustIncrementalAnalyzeManager() RustIncrementalAnalyzeManager()
} }
private val codeAutoCompleteJob: CodeAutoCompleteJob by lazy {
CodeAutoCompleteJob()
}
private val newlineHandler: Array<NewlineHandler> by lazy {
arrayOf<NewlineHandler>(object : NewlineHandler {
override fun matchesRequirement(beforeText: String?, afterText: String?): Boolean {
return true
}
override fun handleNewline(
beforeText: String,
afterText: String?,
tabSize: Int
): NewlineHandleResult {
var text = "\n"
if (beforeText.startsWith("[")) {
if (beforeText.endsWith("_")) {
text = "name]"
} else if (!beforeText.endsWith("]")) {
text = "]"
}
}
val newlineHandleResult = NewlineHandleResult(text, 0)
return newlineHandleResult
}
})
}
private val autoCompleteProvider: RustAutoCompleteProvider by lazy {
val a = RustAutoCompleteProvider()
a.addJob(codeAutoCompleteJob)
a
}
private var codeDataBase: CodeDataBase? = null
/** /**
@ -44,8 +73,8 @@ class RustLanguage(
* @param codeDataBean CodeDataBase * @param codeDataBean CodeDataBase
*/ */
fun setCodeDataBase(codeDataBase: CodeDataBase) { fun setCodeDataBase(codeDataBase: CodeDataBase) {
mRustAnalyzer.setCodeDataBase(codeDataBase) this.codeDataBase = codeDataBase
// autoComplete.setCodeDataBase(codeDataBase) this.codeAutoCompleteJob.setCodeDataBase(codeDataBase)
} }
/** /**
@ -57,35 +86,10 @@ class RustLanguage(
} }
fun setFileDataBase(fileDataBase: FileDataBase) { fun setFileDataBase(fileDataBase: FileDataBase) {
// autoComplete.setFileDataBase(fileDataBase) codeAutoCompleteJob.setFileDataBase(fileDataBase)
} }
//语法分析器
// override fun getAnalyzer(): CodeAnalyzer {
// return mRustAnalyzer
// }
//自动完成器
// override fun getAutoCompleteProvider(): RustAutoComplete {
// return autoComplete
// }
// /**
// * 是否为自动完成字符
// *
// * @param ch 字符
// * @return 逻辑值
// */
// override fun isAutoCompleteChar(ch: Char): Boolean {
// return when (ch) {
// ':', '.', '_', ' ', ',' -> false
// else -> true
// }
// }
override fun getAnalyzeManager(): AnalyzeManager { override fun getAnalyzeManager(): AnalyzeManager {
return rustAnalyzeManager return rustAnalyzeManager
} }
@ -95,15 +99,17 @@ class RustLanguage(
} }
override fun requireAutoComplete( override fun requireAutoComplete(
p0: ContentReference, contentReference: ContentReference,
p1: CharPosition, charPosition: CharPosition,
p2: CompletionPublisher, completionPublisher: CompletionPublisher,
p3: Bundle bundle: Bundle
) { ) {
val line = p0.getLine(p1.getLine()) autoCompleteProvider.requireAutoComplete(
p2.addItem(RustCompletionItem("121221")) contentReference,
p2.updateList() charPosition,
// autoComplete.requireAutoComplete(line,p2,p1.getLine(),p1.getColumn()) completionPublisher,
bundle
)
} }
override fun getIndentAdvance(p0: ContentReference, p1: Int, p2: Int): Int { override fun getIndentAdvance(p0: ContentReference, p1: Int, p2: Int): Int {
@ -112,7 +118,7 @@ class RustLanguage(
//用标签 //用标签
override fun useTab(): Boolean { override fun useTab(): Boolean {
return true return false
} }
override fun getFormatter(): Formatter { override fun getFormatter(): Formatter {
@ -125,7 +131,7 @@ class RustLanguage(
override fun getNewlineHandlers(): Array<NewlineHandler>? { override fun getNewlineHandlers(): Array<NewlineHandler>? {
//行处理程序,按下回车时 //行处理程序,按下回车时
return null return newlineHandler
} }
@ -137,7 +143,6 @@ class RustLanguage(
} }
override fun setEnglish(englishMode: Boolean) { override fun setEnglish(englishMode: Boolean) {
mRustAnalyzer.setEnglish(englishMode)
// autoComplete.setEnglish(englishMode) // autoComplete.setEnglish(englishMode)
isEnglishMode = englishMode isEnglishMode = englishMode
} }

View File

@ -0,0 +1,50 @@
package com.coldmint.rust.pro.edit.autoComplete
import android.os.Bundle
import com.coldmint.rust.pro.edit.RustAutoComplete
import com.coldmint.rust.pro.edit.RustCompletionItem
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
import io.github.rosemoe.sora.text.CharPosition
import io.github.rosemoe.sora.text.ContentReference
/**
* 自动完成工作接口
*/
interface AutoCompleteJob {
/**
* 获取工作名称
*/
fun getName():String
/**
* 该任务是否需要执行返回true则执行
* @param contentReference ContentReference
* @param charPosition CharPosition
* @return String
*/
fun needPerform(
contentReference: ContentReference,
charPosition: CharPosition
): Boolean
/**
* 请求自动完成
* @param contentReference ContentReference
* @param charPosition CharPosition
* @param completionPublisher CompletionPublisher
* @param bundle Bundle
* @return ArrayList<RustCompletionItem>
*/
fun requireAutoComplete(
contentReference: ContentReference,
charPosition: CharPosition,
completionPublisher: CompletionPublisher,
lineData: String,
keyWord:String
)
}

View File

@ -0,0 +1,409 @@
package com.coldmint.rust.pro.edit.autoComplete
import android.os.Bundle
import com.coldmint.rust.core.SourceFile
import com.coldmint.rust.core.database.code.CodeDao
import com.coldmint.rust.core.database.code.CodeDataBase
import com.coldmint.rust.core.database.file.FileDataBase
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.core.tool.LineParser
import com.coldmint.rust.pro.edit.RustAnalyzer
import com.coldmint.rust.pro.edit.RustAutoComplete
import com.coldmint.rust.pro.edit.RustCompletionItem
import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.CompletionItemConverter
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
import io.github.rosemoe.sora.text.CharPosition
import io.github.rosemoe.sora.text.ContentReference
import io.github.rosemoe.sora.widget.CodeEditor
/**
* 代码自动完成项目来自数据库
*/
class CodeAutoCompleteJob : AutoCompleteJob {
private val debugKey = "代码自动完成(数据库)"
private var codeDataBase: CodeDataBase? = null
private var fileDataBase: FileDataBase? = null
private lateinit var codeDao: CodeDao
private val identifiersPromptNumber: Int by lazy {
AppSettings.getValue(AppSettings.Setting.IdentifiersPromptNumber, 40)
}
private var sectionNameMap: HashMap<String, String> = HashMap()
private val lineParser by lazy {
val tem = LineParser()
tem.symbol = ","
tem
}
/**
* 设置代码数据库
* @param codeDataBase CodeDataBase
*/
fun setCodeDataBase(codeDataBase: CodeDataBase) {
DebugHelper.printLog(debugKey, "已链接数据库,数据库状态:${codeDataBase.isOpen}")
this.codeDataBase = codeDataBase
this.codeDao = codeDataBase.getCodeDao()
}
/**
* 设置文件数据库
* @param fileDataBase FileDataBase
*/
fun setFileDataBase(fileDataBase: FileDataBase) {
DebugHelper.printLog(debugKey, "已链接文件数据库,数据库状态:${fileDataBase.isOpen}")
this.fileDataBase = fileDataBase
}
/**
* 是否为英文模式
*/
private val isEnglishMode by lazy {
AppSettings.getValue(AppSettings.Setting.EnglishEditingMode, false)
}
override fun getName(): String {
return debugKey
}
override fun needPerform(
contentReference: ContentReference,
charPosition: CharPosition
): Boolean {
return true
}
override fun requireAutoComplete(
contentReference: ContentReference,
charPosition: CharPosition,
completionPublisher: CompletionPublisher,
lineData: String,
keyWord: String
) {
if (codeDataBase == null) {
DebugHelper.printLog(debugKey, "数据库为空,无法使用", isError = true)
return
}
DebugHelper.printLog(
debugKey,
"行内容[" + lineData + "]关键字[" + keyWord + "]",
"关联提示列表分析"
)
if (lineData.startsWith('[')) {
//搜索节
val name = lineData.subSequence(1, lineData.length).toString()
val list = if (isEnglishMode) {
codeDataBase!!.getSectionDao()
.searchSectionInfoByCode(name, limitNum = identifiersPromptNumber)
} else {
codeDataBase!!.getSectionDao()
.searchSectionInfoByTranslate(name, limitNum = identifiersPromptNumber)
}
list?.forEach {
completionPublisher.addItem(CompletionItemConverter.sectionInfoToCompletionItem(it))
}
} else {
val key = ":"
val keyIndex = lineData.lastIndexOf(key)
if (keyIndex > -1) {
//检查是否可响应变量
val start = "\${"
val end = "}"
val startIndex = lineData.lastIndexOf(start)
if (startIndex > -1) {
val endIndex = lineData.lastIndexOf(end)
if (endIndex < startIndex) {
//如果}的位置小于${的位置,说明没有闭合
val keyWord =
lineData.subSequence(startIndex + start.length, lineData.length)
.toString()
val previousText =
lineData.subSequence(keyIndex + key.length, startIndex).toString()
if (keyWord.isNotBlank()) {
RustAnalyzer.localVariableNameList.forEach {
if (it.name.contains(keyWord)) {
completionPublisher.addItem(
CompletionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
} else {
RustAnalyzer.localVariableNameList.forEach {
completionPublisher.addItem(
CompletionItemConverter.localVariableNameToCompletionItem(
it, previousText
)
)
}
}
// RustAutoComplete.keyWord = keyWord
return
}
}
// val value =
// lineData.subSequence(keyIndex + key.length, lineData.length).toString().trim()
// Log.d("值", value)
//搜索值
// frontIndex 前面冒号的位置
val frontIndex = lineData.lastIndexOf(key, keyIndex - key.length)
val keyValue = if (frontIndex > -1) {
lineData.subSequence(frontIndex + key.length, keyIndex)
} else {
lineData.subSequence(0, keyIndex)
}
val codeInfo =
if (isEnglishMode) {
codeDao.findCodeByCode(keyValue.toString())
} else {
codeDao.findCodeByTranslate(keyValue.toString())
}
DebugHelper.printLog(
debugKey,
"值[" + keyValue + "]英文模式[" + isEnglishMode + "]代码信息[" + codeInfo + "]关键字[" + keyWord + "]",
"值检查"
)
if (codeInfo != null) {
val typeInfo = CompletionItemConverter.getValueType(codeInfo.type)
//获取代码的关联列表
if (typeInfo != null && typeInfo.list.isNotBlank()) {
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]自动提示列表[" + typeInfo.list + "]", "关联提示"
)
lineParser.text = typeInfo.list
lineParser.analyse { lineNum, lineData, isEnd ->
//分析关联提示项目
val temCodeInfo =
codeDao.findCodeByCode(lineData)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是代码[" + (temCodeInfo != null) + "]",
"关联提示列表分析"
)
if (temCodeInfo == null) {
if (lineData.startsWith("@file(") && lineData.endsWith(")")) {
val fileType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
)
val fileInfo = fileDataBase!!.getFileInfoDao()
.searchFileInfoByNameAndType(
keyWord,
fileType.toString(),
identifiersPromptNumber
)
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]搜索了[" + fileType + "]类型的文件,返回了[" + (fileInfo?.size
?: -1) + "]个结果",
"关联提示列表分析"
)
if (fileInfo != null && fileInfo.isNotEmpty()) {
for (fileTable in fileInfo) {
completionPublisher.addItem(
CompletionItemConverter.fileTableToCompletionItem(
fileTable
)
)
}
}
} else if (lineData.startsWith("@customType(") && lineData.endsWith(
")"
)
) {
//用户自动值类型提示
val customType = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
fileDataBase!!.getValueDao()
.searchValueByKey(
keyWord,
customType,
identifiersPromptNumber
)
?.forEach {
completionPublisher.addItem(
CompletionItemConverter.valueTableToCompletionItem(
it
)
)
}
} else if (lineData.startsWith("@type(") && lineData.endsWith(")")) {
val type = lineData.subSequence(
lineData.indexOf('(') + 1,
lineData.indexOf(')')
).toString()
val list = if (isEnglishMode
) {
codeDao.findCodeByCodeInType(
keyWord,
type,
identifiersPromptNumber
)
} else {
codeDao.findCodeByTranslateInType(
keyWord,
type,
identifiersPromptNumber
)
}
DebugHelper.printLog(
debugKey,
"关联了值类型[" + type + "]获取[" + (list?.size ?: -1) + "]个结果",
"值类型引用"
)
if (!list.isNullOrEmpty()) {
list.forEach {
completionPublisher.addItem(
CompletionItemConverter.codeInfoToCompletionItem(
it
)
)
}
}
} else if (lineData.startsWith("@section") && lineData.endsWith(
")"
)
) {
// val section = lineData.subSequence(
// lineData.indexOf('(') + 1,
// lineData.indexOf(')')
// ).toString()
// codeEditor!!.textAnalyzeResult.navigation.forEach {
// if (section == getSectionType(it.label)) {
// result.add(
// CompletionItemConverter.navigationItemToCompletionItem(
// it
// )
// )
// }
// }
} else {
//无法分析的关联项目
// result.add(
// CompletionItem(
// lineData,
// String.format(
// CompletionItemConverter.associatedTip,
// codeInfo.translate
// )
// )
// )
}
} else {
val show = if (isEnglishMode) {
temCodeInfo.code.contains(keyWord)
} else {
temCodeInfo.translate.contains(keyWord)
}
DebugHelper.printLog(
debugKey,
"值类型[" + codeInfo.type + "]项目[" + lineData + "]是否包含" + keyWord + "关键字[" + show + "]",
"关联提示列表分析"
)
if (show) {
completionPublisher.addItem(
CompletionItemConverter.codeInfoToCompletionItem(
temCodeInfo
)
)
}
}
true
}
}
}
} else {
//如果不包含:搜索键
val lineNumber = charPosition.getLine()
val section = getSection(lineNumber, contentReference)
//如果不在任何节内
if (section == null) {
DebugHelper.printLog(debugKey, "不在任何节内,无法提示。", isError = true)
return
}
val trueSection = getSectionType(section)
val list = if (isEnglishMode) {
codeDao.findCodeByEnglishCodeKeyFromSection(
keyWord,
trueSection,
identifiersPromptNumber
)
} else {
codeDao
.findCodeByKeyFromSection(keyWord, trueSection, identifiersPromptNumber)
}
if (list != null && list.isNotEmpty()) {
list.forEach {
completionPublisher.addItem(
CompletionItemConverter.codeInfoToCompletionItem(it)
)
}
} else {
DebugHelper.printLog(
debugKey,
"${trueSection}节模糊搜索${keyWord}无结果。",
isError = true
)
}
}
}
}
/**
* 获取光标前的节名
* @param lineNumber Int
* @param contentReference ContentReference
* @return String?
*/
fun getSection(lineNumber: Int, contentReference: ContentReference): String? {
return if (lineNumber > 0) {
for (i in lineNumber downTo 0) {
val lineData = contentReference.getLine(i)
DebugHelper.printLog(debugKey, "检查第${i}${lineData}", "获取光标前的节名")
if (lineData.startsWith("[") && lineData.endsWith("]")) {
val name = lineData.subSequence(1, lineData.length - 1).toString()
DebugHelper.printLog(debugKey, "返回 ${name}", "获取光标前的节名")
return name
}
}
DebugHelper.printLog(debugKey, "没有找到节。", "获取光标前的节名", isError = true)
null
} else {
DebugHelper.printLog(debugKey, "行号小于0无法获取。", "获取光标前的节名", isError = true)
null
}
}
/**
* 获取节类型(永远返回英文)
* @param section String
* @return String
*/
fun getSectionType(section: String): String {
if (sectionNameMap.containsKey(section)) {
return sectionNameMap[section] ?: SourceFile.getSectionType(section)
}
val result = if (isEnglishMode) {
SourceFile.getSectionType(section)
} else {
val sectionInfo = codeDataBase!!.getSectionDao()
.findSectionInfoByTranslate(SourceFile.getSectionType(section))
sectionInfo?.code ?: SourceFile.getSectionType(section)
}
sectionNameMap[section] = result
return result
}
}

View File

@ -9,6 +9,7 @@ import kotlin.Throws
import android.os.Environment import android.os.Environment
import android.util.Log import android.util.Log
import com.hjq.language.MultiLanguages import com.hjq.language.MultiLanguages
import java.io.File
import java.lang.NullPointerException import java.lang.NullPointerException
import java.util.* import java.util.*
@ -37,10 +38,24 @@ object AppSettings {
} }
enum class Setting { enum class Setting {
DatabaseDirectory, DatabasePath, TemplateDirectory, AppLanguage, DeveloperMode, CustomSymbol, AutoCreateNomedia, OnlyLoadConantLanguageTemple, NightMode, GamePackage, KeepRwmodFile, EnableRecoveryStation, RecoveryStationFileSaveDays, RecoveryStationFolder, IndependentFolder, SetGameStorage, PackDirectory, IdentifiersPromptNumber, UserName, UseJetBrainsMonoFont, AppID, Account, PassWord, ExpirationTime, CheckBetaUpdate, UpdateData, ShareTip, AgreePolicy, EnglishEditingMode, NightModeFollowSystem, UseMobileNetwork, MapFolder, ModFolder, UseTheCommunityAsTheLaunchPage, AutoSave, ServerAddress, Token, LoginStatus, DynamicColor, ExperiencePlan, FileSortType DatabaseDirectory, DatabasePath, TemplateDirectory, AppLanguage, DeveloperMode, CustomSymbol, AutoCreateNomedia, OnlyLoadConantLanguageTemple, NightMode, GamePackage, KeywordColor, AnnotationColor, TextColor, SectionColor, KeepRwmodFile, EnableRecoveryStation, RecoveryStationFileSaveDays, RecoveryStationFolder, IndependentFolder, SetGameStorage, PackDirectory, IdentifiersPromptNumber, UserName, UseJetBrainsMonoFont, AppID, Account, PassWord, ExpirationTime, CheckBetaUpdate, UpdateData, ShareTip, AgreePolicy, EnglishEditingMode, NightModeFollowSystem, UseMobileNetwork, MapFolder, ModFolder, UseTheCommunityAsTheLaunchPage, AutoSave, ServerAddress, Token, LoginStatus, DynamicColor, ExperiencePlan, FileSortType, CodeEditBackGroundEnable, BlurTransformationValue, CodeEditBackGroundPath
} }
/**
* 创建新的编辑器背景文件(返回文件目录)
* @return String
*/
fun createNewCodeEditBackGroundFile(): String {
val folderPath = mApplication.filesDir.absolutePath + "/CodeEditBackground/"
val folder = File(folderPath)
if (!folder.exists()) {
folder.mkdirs()
}
return folderPath + UUID.randomUUID().toString() + ".png"
}
private val map: HashMap<Setting, String> = HashMap<Setting, String>() private val map: HashMap<Setting, String> = HashMap<Setting, String>()
/** /**
@ -127,6 +142,14 @@ object AppSettings {
map[Setting.AgreePolicy] = "AgreePolicy" map[Setting.AgreePolicy] = "AgreePolicy"
map[Setting.LoginStatus] = "LoginStatus" map[Setting.LoginStatus] = "LoginStatus"
map[Setting.Token] = "Token" map[Setting.Token] = "Token"
map[Setting.BlurTransformationValue] = "BlurTransformationValue"
map[Setting.CodeEditBackGroundEnable] = "CodeEditBackGroundEnable"
map[Setting.CodeEditBackGroundPath] = "CodeEditBackGroundPath"
//KeywordColor, AnnotationColor, TextColor, SectionColor
map[Setting.KeywordColor] = mApplication.getString(R.string.setting_keyword_color)
map[Setting.AnnotationColor] = mApplication.getString(R.string.setting_annotation_color)
map[Setting.TextColor] = mApplication.getString(R.string.setting_text_color)
map[Setting.SectionColor] = mApplication.getString(R.string.setting_section_color)
} }
/** /**

View File

@ -33,13 +33,8 @@ import java.lang.StringBuilder
* @property canUseFileConversion Boolean * @property canUseFileConversion Boolean
* @property valueTypeDao ValueTypeDao? * @property valueTypeDao ValueTypeDao?
*/ */
class CompletionItemConverter private constructor() : EnglishMode { object CompletionItemConverter {
companion object {
val instance: CompletionItemConverter by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
CompletionItemConverter()
}
}
/** /**
* 初始化 * 初始化
@ -80,14 +75,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
HashMap() HashMap()
} }
private var isEnglishMode = false private var isEnglishMode = false
get() = AppSettings.getValue(AppSettings.Setting.EnglishEditingMode, false)
override fun isEnglishMode(): Boolean {
return isEnglishMode
}
override fun setEnglish(englishMode: Boolean) {
this.isEnglishMode = englishMode
}
/** /**
@ -135,7 +123,7 @@ class CompletionItemConverter private constructor() : EnglishMode {
NullPointerException("没有初始化。") NullPointerException("没有初始化。")
} }
val end = if (sectionInfo.needName) { val end = if (sectionInfo.needName) {
"_]" "_"
} else { } else {
"]" "]"
@ -213,12 +201,12 @@ class CompletionItemConverter private constructor() : EnglishMode {
codeInfo.description, boxDrawable codeInfo.description, boxDrawable
) )
} }
val typeList = typeInfo?.list // val typeList = typeInfo?.list
if (typeList != null && typeList.isNotBlank()) { // if (typeList != null && typeList.isNotBlank()) {
val bundle = Bundle() // val bundle = Bundle()
bundle.putString("list", typeList) // bundle.putString("list", typeList)
// completionItem.extrasData = bundle // completionItem.extrasData = bundle
} // }
val offset = typeInfo?.offset val offset = typeInfo?.offset
if (offset != null && offset.isNotBlank()) { if (offset != null && offset.isNotBlank()) {
//如果偏移不为空 //如果偏移不为空

View File

@ -43,6 +43,7 @@ object GlobalMethod {
const val DEBUG_SIGN = "963dfd616924b27f9247a35e45bc130a" const val DEBUG_SIGN = "963dfd616924b27f9247a35e45bc130a"
const val RELEASE_SIGN = "5320b24894fe7ed449842a81a2dfceda" const val RELEASE_SIGN = "5320b24894fe7ed449842a81a2dfceda"
/** /**
* 获取主题色 * 获取主题色
* *
@ -107,6 +108,87 @@ object GlobalMethod {
return requestOptions return requestOptions
} }
/**
* int颜色值转String
* @param color Int
* @param useARGB Boolean
* @return String
*/
fun colorToString(color: Int, useARGB: Boolean = true): String {
val builder = StringBuilder()
builder.append('#')
if (useARGB) {
builder.append(convertDigital(Color.alpha(color)))
}
builder.append(convertDigital(Color.red(color)))
builder.append(convertDigital(Color.green(color)))
builder.append(convertDigital(Color.blue(color)))
return builder.toString()
}
/**
* 展示颜色选择对话框
* @param context Context
* @param func Function1<String, Unit>
*/
fun showColorPickerDialog(
context: Context,
useARGB: Boolean = false, func: ((String) -> Unit)
) {
ColorPickerDialogBuilder
.with(context).showAlphaSlider(useARGB)
.setTitle(context.getString(R.string.choose_color))
.initialColor(Color.WHITE)
.wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
.density(12)
.setOnColorSelectedListener {
//toast("onColorSelected: 0x" + Integer.toHexString(selectedColor));
}
.setPositiveButton(R.string.dialog_ok) { dialog, selectedColor, allColors ->
func.invoke(colorToString(selectedColor, useARGB))
}
.setNegativeButton(R.string.dialog_cancel) { dialog, which -> }
.build()
.show()
}
/**
* 转换为16进制
*
* @param num 十进制整数
* @return 16进制数
*/
private fun convertDigital(num: Int): String {
return if (num > 255) {
"FF"
} else {
val builder = java.lang.StringBuilder()
val result = num / 16
val remainder = num % 16
when (result) {
10 -> builder.append('A')
11 -> builder.append('B')
12 -> builder.append('C')
13 -> builder.append('D')
14 -> builder.append('E')
15 -> builder.append('F')
else -> builder.append(result)
}
when (remainder) {
10 -> builder.append('A')
11 -> builder.append('B')
12 -> builder.append('C')
13 -> builder.append('D')
14 -> builder.append('E')
15 -> builder.append('F')
else -> builder.append(remainder)
}
builder.toString()
}
}
/** /**
* 显示更新日志 * 显示更新日志
* @param context Context * @param context Context
@ -191,7 +273,6 @@ object GlobalMethod {
} }
//设置删除线 //设置删除线
fun addDeleteLine(vararg textViews: TextView?) { fun addDeleteLine(vararg textViews: TextView?) {
for (textView in textViews) { for (textView in textViews) {

View File

@ -17,6 +17,7 @@ import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.pro.base.BaseAndroidViewModel import com.coldmint.rust.pro.base.BaseAndroidViewModel
import com.coldmint.rust.pro.livedata.OpenedSourceFileListLiveData import com.coldmint.rust.pro.livedata.OpenedSourceFileListLiveData
import com.coldmint.rust.pro.tool.AppSettings import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.CompletionItemConverter
import com.coldmint.rust.pro.tool.GlobalMethod import com.coldmint.rust.pro.tool.GlobalMethod
import java.io.File import java.io.File
import java.lang.StringBuilder import java.lang.StringBuilder
@ -189,6 +190,7 @@ class EditViewModel(application: Application) : BaseAndroidViewModel(application
} }
override fun onTranslateComplete(code: String) { override fun onTranslateComplete(code: String) {
CompletionItemConverter.setSourceFilePath(path)
val openedSourceFile = OpenedSourceFile(path) val openedSourceFile = OpenedSourceFile(path)
openedSourceFile.setTranslation(code) openedSourceFile.setTranslation(code)
val index = openedSourceFileListLiveData.add(openedSourceFile) val index = openedSourceFileListLiveData.add(openedSourceFile)
@ -534,40 +536,7 @@ class EditViewModel(application: Application) : BaseAndroidViewModel(application
} }
} }
/**
* 转换为16进制
*
* @param num 十进制整数
* @return 16进制数
*/
fun convertDigital(num: Int): String {
return if (num > 255) {
"FF"
} else {
val builder = StringBuilder()
val result = num / 16
val remainder = num % 16
when (result) {
10 -> builder.append('A')
11 -> builder.append('B')
12 -> builder.append('C')
13 -> builder.append('D')
14 -> builder.append('E')
15 -> builder.append('F')
else -> builder.append(result)
}
when (remainder) {
10 -> builder.append('A')
11 -> builder.append('B')
12 -> builder.append('C')
13 -> builder.append('D')
14 -> builder.append('E')
15 -> builder.append('F')
else -> builder.append(remainder)
}
builder.toString()
}
}
/** /**
* 加载数据 * 加载数据

View File

@ -178,29 +178,26 @@ class FileManagerViewModel : BaseViewModel() {
return rootPath return rootPath
} }
// /** /**
// * 解析文件路径 * 解析文件路径
// * *
// * @param context 上下文环境 * @param context 上下文环境
// * @param intent 意图 * @param uri 定位符
// * @return 成功返回文件路径失败返回null * @return 成功返回文件路径失败返回null
// */ */
fun parseFilePath(context: Context, intent: Intent?): String? { fun parseFilePath(context: Context, uri: Uri?): String? {
return try { return try {
if (intent != null) { var chooseFilePath: String? = null
val uri = intent.data if ("file".equals(uri!!.scheme, ignoreCase = true)) { //使用第三方应用打开
var chooseFilePath: String? = null chooseFilePath = uri.path
if ("file".equals(uri!!.scheme, ignoreCase = true)) { //使用第三方应用打开
chooseFilePath = uri.path
return chooseFilePath
}
chooseFilePath = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { //4.4以后
getPath(context, uri)
} else { //4.4以下下系统调用方法
getRealPathFromURI(context, uri)
}
return chooseFilePath return chooseFilePath
} }
chooseFilePath = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { //4.4以后
getPath(context, uri)
} else { //4.4以下下系统调用方法
getRealPathFromURI(context, uri)
}
return chooseFilePath
null null
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@ -239,7 +236,6 @@ class FileManagerViewModel : BaseViewModel() {
return@launch return@launch
} }
val arrayList = ArrayList<File?>() val arrayList = ArrayList<File?>()
Log.d("文件管理器", "当前路径" + path + "根路径" + rootPath + "添加返回" + (path != rootPath))
if (path != rootPath) { if (path != rootPath) {
//如果不是根目录添加返回 //如果不是根目录添加返回
arrayList.add(null) arrayList.add(null)

View File

@ -238,12 +238,23 @@ class StartViewModel(application: Application) : BaseAndroidViewModel(applicatio
AppSettings.initSetting(AppSettings.Setting.AutoSave, true) AppSettings.initSetting(AppSettings.Setting.AutoSave, true)
AppSettings.initSetting(AppSettings.Setting.AgreePolicy, false) AppSettings.initSetting(AppSettings.Setting.AgreePolicy, false)
AppSettings.initSetting(AppSettings.Setting.LoginStatus, false) AppSettings.initSetting(AppSettings.Setting.LoginStatus, false)
AppSettings.initSetting(AppSettings.Setting.FileSortType,context.getString(R.string.setting_file_list_action_sort_by_name)) AppSettings.initSetting(
AppSettings.Setting.FileSortType,
context.getString(R.string.setting_file_list_action_sort_by_name)
)
//如果启用动态颜色 //如果启用动态颜色
AppSettings.initSetting( AppSettings.initSetting(
AppSettings.Setting.DynamicColor, AppSettings.Setting.DynamicColor,
DynamicColors.isDynamicColorAvailable() DynamicColors.isDynamicColorAvailable()
) )
AppSettings.initSetting(AppSettings.Setting.KeywordColor, "#FF0031C2")
AppSettings.initSetting(AppSettings.Setting.SectionColor, "#FFE10000")
AppSettings.initSetting(AppSettings.Setting.TextColor, "#FF000000")
AppSettings.initSetting(AppSettings.Setting.AnnotationColor, "#FF00AF2C")
AppSettings.initSetting(AppSettings.Setting.CodeEditBackGroundEnable, false)
AppSettings.initSetting(AppSettings.Setting.BlurTransformationValue, 1)
AppSettings.initSetting(AppSettings.Setting.CodeEditBackGroundPath, "")
} }
/** /**

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#000000" <vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/> <path android:fillColor="@android:color/white" android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#000000" <vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3.9,12c0,-1.71 1.39,-3.1 3.1,-3.1h4L11,7L7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5h4v-1.9L7,15.1c-1.71,0 -3.1,-1.39 -3.1,-3.1zM8,13h8v-2L8,11v2zM17,7h-4v1.9h4c1.71,0 3.1,1.39 3.1,3.1s-1.39,3.1 -3.1,3.1h-4L13,17h4c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5z"/> <path android:fillColor="@android:color/white" android:pathData="M3.9,12c0,-1.71 1.39,-3.1 3.1,-3.1h4L11,7L7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5h4v-1.9L7,15.1c-1.71,0 -3.1,-1.39 -3.1,-3.1zM8,13h8v-2L8,11v2zM17,7h-4v1.9h4c1.71,0 3.1,1.39 3.1,3.1s-1.39,3.1 -3.1,3.1h-4L13,17h4c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5z"/>

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#000000" <vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/> <path android:fillColor="@android:color/white" android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/>

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#000000" <vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M15,7v12.97l-4.21,-1.81 -0.79,-0.34 -0.79,0.34L5,19.97L5,7h10m4,-6L8.99,1C7.89,1 7,1.9 7,3h10c1.1,0 2,0.9 2,2v13l2,1L21,3c0,-1.1 -0.9,-2 -2,-2zM15,5L5,5c-1.1,0 -2,0.9 -2,2v16l7,-3 7,3L17,7c0,-1.1 -0.9,-2 -2,-2z"/> <path android:fillColor="@android:color/white" android:pathData="M15,7v12.97l-4.21,-1.81 -0.79,-0.34 -0.79,0.34L5,19.97L5,7h10m4,-6L8.99,1C7.89,1 7,1.9 7,3h10c1.1,0 2,0.9 2,2v13l2,1L21,3c0,-1.1 -0.9,-2 -2,-2zM15,5L5,5c-1.1,0 -2,0.9 -2,2v16l7,-3 7,3L17,7c0,-1.1 -0.9,-2 -2,-2z"/>

View File

@ -0,0 +1,6 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,22C6.49,22 2,17.51 2,12S6.49,2 12,2s10,4.04 10,9c0,3.31 -2.69,6 -6,6h-1.77c-0.28,0 -0.5,0.22 -0.5,0.5 0,0.12 0.05,0.23 0.13,0.33 0.41,0.47 0.64,1.06 0.64,1.67 0,1.38 -1.12,2.5 -2.5,2.5zM12,4c-4.41,0 -8,3.59 -8,8s3.59,8 8,8c0.28,0 0.5,-0.22 0.5,-0.5 0,-0.16 -0.08,-0.28 -0.14,-0.35 -0.41,-0.46 -0.63,-1.05 -0.63,-1.65 0,-1.38 1.12,-2.5 2.5,-2.5L16,15c2.21,0 4,-1.79 4,-4 0,-3.86 -3.59,-7 -8,-7z"/>
<path android:fillColor="@android:color/white" android:pathData="M6.5,11.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="@android:color/white" android:pathData="M9.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="@android:color/white" android:pathData="M14.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="@android:color/white" android:pathData="M17.5,11.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
</vector>

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#000000" <vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM5.92,19H5v-0.92l9.06,-9.06 0.92,0.92L5.92,19zM20.71,5.63l-2.34,-2.34c-0.2,-0.2 -0.45,-0.29 -0.71,-0.29s-0.51,0.1 -0.7,0.29l-1.83,1.83 3.75,3.75 1.83,-1.83c0.39,-0.39 0.39,-1.02 0,-1.41z"/> <path android:fillColor="@android:color/white" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM5.92,19H5v-0.92l9.06,-9.06 0.92,0.92L5.92,19zM20.71,5.63l-2.34,-2.34c-0.2,-0.2 -0.45,-0.29 -0.71,-0.29s-0.51,0.1 -0.7,0.29l-1.83,1.83 3.75,3.75 1.83,-1.83c0.39,-0.39 0.39,-1.02 0,-1.41z"/>

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#000000" <vector android:height="24dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/> <path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>

View File

@ -1,5 +1,11 @@
<vector android:height="24dp" android:tint="#000000" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM19,19L5,19L5,5h11.17L19,7.83L19,19zM12,12c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM6,6h9v4L6,10z"/> android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM19,19L5,19L5,5h11.17L19,7.83L19,19zM12,12c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM6,6h9v4L6,10z" />
</vector> </vector>

View File

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="?attr/colorControlNormal" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M4.01,6.03l7.51,3.22 -7.52,-1 0.01,-2.22m7.5,8.72L4,17.97v-2.22l7.51,-1M2.01,3L2,10l15,2 -15,2 0.01,7L23,12 2.01,3z"/>
</vector>

View File

@ -1,5 +1,11 @@
<vector android:height="24dp" android:tint="#000000" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<path android:fillColor="@android:color/white" android:pathData="M15.55,13c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.37,-0.66 -0.11,-1.48 -0.87,-1.48L5.21,4l-0.94,-2L1,2v2h2l3.6,7.59 -1.35,2.44C4.52,15.37 5.48,17 7,17h12v-2L7,15l1.1,-2h7.45zM6.16,6h12.15l-2.76,5L8.53,11L6.16,6zM7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/> android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M15.55,13c0.75,0 1.41,-0.41 1.75,-1.03l3.58,-6.49c0.37,-0.66 -0.11,-1.48 -0.87,-1.48L5.21,4l-0.94,-2L1,2v2h2l3.6,7.59 -1.35,2.44C4.52,15.37 5.48,17 7,17h12v-2L7,15l1.1,-2h7.45zM6.16,6h12.15l-2.76,5L8.53,11L6.16,6zM7,18c-1.1,0 -1.99,0.9 -1.99,2S5.9,22 7,22s2,-0.9 2,-2 -0.9,-2 -2,-2zM17,18c-1.1,0 -1.99,0.9 -1.99,2s0.89,2 1.99,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
</vector> </vector>

View File

@ -1,6 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="215.23438dp" android:width="215.23438dp"
android:height="200dp" android:height="200dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="1102" android:viewportWidth="1102"
android:viewportHeight="1024"> android:viewportHeight="1024">
<path <path

View File

@ -1,6 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp" android:width="200dp"
android:height="200dp" android:height="200dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="1024" android:viewportWidth="1024"
android:viewportHeight="1024"> android:viewportHeight="1024">
<path <path

View File

@ -1,6 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp" android:width="200dp"
android:height="200dp" android:height="200dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="1024" android:viewportWidth="1024"
android:viewportHeight="1024"> android:viewportHeight="1024">
<path <path

View File

@ -0,0 +1,269 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.Material3.HeadlineSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/edit_text_color" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/keywordColorEditLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:endIconCheckable="true"
app:endIconDrawable="@drawable/ic_outline_color_lens_24"
app:endIconMode="custom">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/keywordColorEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="@string/keyword_color"
android:imeOptions="actionNext"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/sectionColorEditLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:endIconCheckable="true"
app:endIconDrawable="@drawable/ic_outline_color_lens_24"
app:endIconMode="custom">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/sectionColorEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="@string/section_color"
android:imeOptions="actionNext"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textColorEditLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:endIconCheckable="true"
app:endIconDrawable="@drawable/ic_outline_color_lens_24"
app:endIconMode="custom">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textColorEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="@string/text_color"
android:imeOptions="actionNext"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/annotationColorEditLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:endIconCheckable="true"
app:endIconDrawable="@drawable/ic_outline_color_lens_24"
app:endIconMode="custom">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/annotationColorEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="@string/annotation_color"
android:imeOptions="actionDone"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/resetButton"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/restore_default" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="48dp">
<LinearLayout
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.Material3.HeadlineSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/edit_background" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/filePathInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:endIconCheckable="true"
app:endIconDrawable="@drawable/file"
app:endIconMode="custom">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/filePathInputEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="@string/file_path"
android:imeOptions="actionDone"
android:inputType="textMultiLine" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/dimCardView"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<TextView
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dim_value" />
<com.google.android.material.slider.Slider
android:id="@+id/slide"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:stepSize="1.0"
android:valueFrom="1.0"
android:valueTo="30.0" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/imageCardView"
android:visibility="gone"
style="@style/Widget.Material3.CardView.Outlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="450dp"
android:scaleType="centerCrop" />
</com.google.android.material.card.MaterialCardView>
<Button
android:visibility="gone"
android:id="@+id/autoGenerateColorSchemeButton"
android:text="@string/auto_generate_color_scheme"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:text="@string/edit_function"
app:icon="@drawable/round_save_20" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -15,7 +15,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:background="?android:attr/windowBackground" android:background="@android:color/transparent"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar

View File

@ -62,12 +62,22 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/mod_icon" /> android:text="@string/mod_icon" />
<ImageView <com.google.android.material.card.MaterialCardView
android:id="@+id/iconView" style="@style/Widget.Material3.CardView.Filled"
android:layout_width="80dp" android:layout_width="wrap_content"
android:layout_height="80dp" android:layout_marginLeft="8dp"
android:layout_margin="8dp" android:layout_height="wrap_content">
android:src="@drawable/image" />
<ImageView
android:scaleType="centerCrop"
android:id="@+id/iconView"
android:layout_width="72dp"
android:layout_height="72dp"
android:src="@drawable/image" />
</com.google.android.material.card.MaterialCardView>
</LinearLayout> </LinearLayout>

View File

@ -20,7 +20,6 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -35,32 +34,31 @@
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp">
app:cardElevation="2dp"
card_view:cardCornerRadius="2dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="8dp" android:layout_margin="16dp"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
style="@style/TextAppearance.Material3.HeadlineSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/required" android:text="@string/required" />
android:textSize="16sp" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/modIdInputLayout" android:id="@+id/modIdInputLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
app:counterEnabled="true" app:counterEnabled="true"
app:counterMaxLength="30" app:counterMaxLength="30"
app:helperText="@string/id_tip"> app:helperText="@string/id_tip">
@ -189,34 +187,34 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:visibility="gone" /> android:visibility="gone" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="16dp">
app:cardElevation="2dp"
card_view:cardCornerRadius="2dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="8dp" android:layout_margin="16dp"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
style="@style/TextAppearance.Material3.HeadlineSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/selectable" android:text="@string/selectable" />
android:textSize="16dp" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:gravity="center_vertical"> android:gravity="center_vertical">
<TextView <TextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/mod_icon" /> android:text="@string/mod_icon" />
@ -238,6 +236,7 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/screenshot" /> android:text="@string/screenshot" />
@ -245,10 +244,12 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/screenshotRecyclerView" android:id="@+id/screenshotRecyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" /> android:layout_height="200dp"
android:layout_marginTop="8dp" />
<Button <Button
android:id="@+id/addScreenshotButton" android:id="@+id/addScreenshotButton"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/add" /> android:text="@string/add" />
@ -256,42 +257,41 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="16dp">
app:cardElevation="2dp"
card_view:cardCornerRadius="2dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="8dp" android:layout_margin="16dp"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
style="@style/TextAppearance.Material3.HeadlineSmall"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/menu_title1" android:text="@string/menu_title1" />
android:textSize="16sp" />
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"> android:layout_marginTop="16dp">
<TextView <TextView
android:id="@+id/modPathView" android:id="@+id/modPathView"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toStartOf="@id/packModButton" android:layout_toStartOf="@id/packModButton"
android:text="@string/unable_load_mod_info" android:text="@string/unable_load_mod_info" />
android:textSize="13sp" />
<Button <Button
android:id="@+id/packModButton" android:id="@+id/packModButton"
@ -311,15 +311,14 @@
android:visibility="gone" /> android:visibility="gone" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
<androidx.cardview.widget.CardView <com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:layout_marginBottom="60dp" android:layout_marginBottom="60dp">
app:cardElevation="2dp"
card_view:cardCornerRadius="2dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -329,32 +328,33 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
style="@style/TextAppearance.Material3.HeadlineMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/dynamic" android:text="@string/dynamic" />
android:textSize="16sp" />
<CheckBox <CheckBox
android:id="@+id/checkbox" android:id="@+id/checkbox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:checked="true" android:checked="true"
android:text="@string/share_to_dynamic" /> android:text="@string/share_to_dynamic" />
</LinearLayout> </LinearLayout>
</androidx.cardview.widget.CardView> </com.google.android.material.card.MaterialCardView>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
<Button <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/releaseButton" android:id="@+id/releaseButton"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom|right"
android:layout_marginLeft="16dp" android:layout_margin="16dp"
android:layout_marginRight="16dp" android:text="@string/release"
android:text="@string/release" /> app:icon="@drawable/ic_outline_send_24" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,34 +1,87 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:fitsSystemWindows="true"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle" android:fitsSystemWindows="true">
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</com.google.android.material.appbar.AppBarLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/relativeLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:paddingLeft="16dp"
android:orientation="vertical"> android:paddingTop="8dp"
android:paddingRight="16dp"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<ImageView <FrameLayout
android:id="@+id/mainImageView" android:id="@+id/frameLayout"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:src="@drawable/image" /> android:layout_alignParentTop="true"
android:layout_gravity="center">
<com.coldmint.rust.core.turret.TurretSketchpadView
android:id="@+id/turretSketchpadView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</RelativeLayout> </RelativeLayout>
</LinearLayout> <FrameLayout
android:id="@+id/standard_bottom_sheet"
style="@style/Widget.Material3.BottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<!-- Drag handle for accessibility -->
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- Bottom sheet contents. -->
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/title"/>-->
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/supporting_text"/>-->
<!-- <Button-->
<!-- android:id="@+id/bottomsheet_button"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/action" />-->
<!-- <com.google.android.material.switchmaterial.SwitchMaterial-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/switch_label"/>-->
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -2,21 +2,30 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:windowBackground"
android:padding="8dp"> android:padding="8dp">
<ImageView <com.google.android.material.card.MaterialCardView
android:id="@+id/iconView" android:id="@+id/iconCardView"
android:layout_width="45dp" style="@style/Widget.Material3.CardView.Filled"
android:layout_height="45dp" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp">
android:src="@drawable/image" />
<ImageView
android:id="@+id/iconView"
android:layout_width="45dp"
android:layout_height="45dp"
android:scaleType="centerCrop"
android:src="@drawable/image" />
</com.google.android.material.card.MaterialCardView>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toEndOf="@id/iconView" android:layout_toEndOf="@id/iconCardView"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView

View File

@ -16,7 +16,6 @@
android:id="@+id/save_text" android:id="@+id/save_text"
android:icon="@drawable/ic_outline_save_24" android:icon="@drawable/ic_outline_save_24"
android:title="@string/edit_function" android:title="@string/edit_function"
app:actionViewClass="view"
app:showAsAction="always" /> app:showAsAction="always" />
<item <item
@ -27,6 +26,7 @@
android:id="@+id/open_game_test" android:id="@+id/open_game_test"
android:title="@string/open_game_test" /> android:title="@string/open_game_test" />
<item <item
android:id="@+id/show_line_number" android:id="@+id/show_line_number"
android:checkable="true" android:checkable="true"
@ -40,8 +40,7 @@
<item <item
android:id="@+id/turret_design" android:id="@+id/turret_design"
android:title="@string/turret_design" android:title="@string/turret_design" />
android:visible="false" />
<item <item
android:id="@+id/search_view" android:id="@+id/search_view"

View File

@ -233,6 +233,7 @@
<!--编译错误--> <!--编译错误-->
<string name="not_save_exit">不保存退出</string> <string name="not_save_exit">不保存退出</string>
<string name="save_settings">检查到配置信息更新,要保存更改嘛?</string>
<string name="saveing">正在保存%1$s...</string> <string name="saveing">正在保存%1$s...</string>
<string name="save_complete">%1$s保存完成。</string> <string name="save_complete">%1$s保存完成。</string>
@ -872,10 +873,26 @@
<string name="setting_file_list_action_sort_by_last_modified" translatable="false">ByLastModified</string> <string name="setting_file_list_action_sort_by_last_modified" translatable="false">ByLastModified</string>
<string name="file_sort_type">文件排序方式</string> <string name="file_sort_type">文件排序方式</string>
<string name="setting_file_sort_type" translatable="false">FileSortType</string> <string name="setting_file_sort_type" translatable="false">FileSortType</string>
<string name="setting_keyword_color" translatable="false">KeywordColor</string>
<string name="setting_annotation_color" translatable="false">AnnotationColor</string>
<string name="setting_text_color" translatable="false">TextColor</string>
<string name="setting_section_color" translatable="false">SectionColor</string>
<string name="template_id">模板id</string> <string name="template_id">模板id</string>
<string name="customize_edit_text">定制编辑框</string>
<string name="subscription">订阅</string> <string name="subscription">订阅</string>
<string name="de_subscription">退订</string> <string name="de_subscription">退订</string>
<string name="de_subscription_msg">要退订%1$s嘛?</string> <string name="de_subscription_msg">要退订%1$s嘛?</string>
<string name="keyword_color">关键字颜色</string>
<string name="text_color">普通文本颜色</string>
<string name="edit_text_color">字体颜色</string>
<string name="section_color">节颜色</string>
<string name="annotation_color">注释颜色</string>
<string name="customize_edit_text_description">定制编辑框字体颜色,编辑框背景图像等等。</string>
<string name="restore_default">恢复默认</string>
<string name="edit_background">背景</string>
<string name="file_path">文件路径</string>
<string name="dim_value">模糊度</string>
<string name="auto_generate_color_scheme">自动生成配色方案</string>
<!-- <string name="search_suggestions_null">无搜索建议。</string>--> <!-- <string name="search_suggestions_null">无搜索建议。</string>-->
<!-- <string name="search_suggestions_number">共%1$d个搜索建议。</string>--> <!-- <string name="search_suggestions_number">共%1$d个搜索建议。</string>-->

View File

@ -107,6 +107,10 @@
app:summary="@string/auto_save_describe" app:summary="@string/auto_save_describe"
app:title="@string/auto_save" /> app:title="@string/auto_save" />
<PreferenceScreen
app:key="customize_edit"
app:title="@string/customize_edit_text"
app:summary="@string/customize_edit_text_description"/>
</PreferenceCategory> </PreferenceCategory>

View File

@ -44,10 +44,10 @@ dependencies {
annotationProcessor "androidx.room:room-compiler:2.4.0" annotationProcessor "androidx.room:room-compiler:2.4.0"
kapt "androidx.room:room-compiler:2.4.0" kapt "androidx.room:room-compiler:2.4.0"
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'com.google.android.material:material:1.5.0' implementation 'com.google.android.material:material:1.7.0-beta01'
implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0' implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
} }

View File

@ -6,6 +6,7 @@ import com.coldmint.rust.core.interfaces.LineParserEvent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Environment import android.os.Environment
import com.coldmint.rust.core.tool.DebugHelper
import com.coldmint.rust.core.tool.FileOperator import com.coldmint.rust.core.tool.FileOperator
import com.coldmint.rust.core.turret.TurretManager import com.coldmint.rust.core.turret.TurretManager
import java.io.File import java.io.File
@ -118,12 +119,14 @@ class SourceFile(text: String) {
fun findResourceFiles(value: String?, checkExists: Boolean): Array<File>? { fun findResourceFiles(value: String?, checkExists: Boolean): Array<File>? {
var value = value var value = value
if (modclass == null || !this::file.isInitialized) { if (modclass == null || !this::file.isInitialized) {
DebugHelper.printLog("搜索资源文件","无法搜索,因为没有初始化文件或模组类。", isError = true)
return null return null
} }
DebugHelper.printLog("搜索资源文件","准备开始 文件路径${file.absolutePath}${value}")
val none = "NONE" val none = "NONE"
val auto = "AUTO" val auto = "AUTO"
val shared = "SHARED" val shared = "SHARED:"
val root = "ROOT" val root = "ROOT:"
return if (value == null || value == none || value == auto || value.startsWith(shared)) { return if (value == null || value == none || value == auto || value.startsWith(shared)) {
null null
} else { } else {
@ -136,11 +139,15 @@ class SourceFile(text: String) {
if (checkExists) { if (checkExists) {
if (target.exists()) { if (target.exists()) {
result.add(target) result.add(target)
}else{
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath}解析Root路径为 ${target.absolutePath} 文件不存在!", isError = true)
} }
} else { } else {
result.add(target) result.add(target)
} }
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath}解析Root路径为 ${target.absolutePath}")
} else if (value.contains(",")) { } else if (value.contains(",")) {
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath}启用多文件解析。")
val lineParser = LineParser(value) val lineParser = LineParser(value)
lineParser.needTrim = true lineParser.needTrim = true
lineParser.symbol = "," lineParser.symbol = ","
@ -156,10 +163,13 @@ class SourceFile(text: String) {
if (checkExists) { if (checkExists) {
if (target.exists()) { if (target.exists()) {
result.add(target) result.add(target)
}else{
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath} 多文件分割 第${lineNum}个文件 ${target.absolutePath} 不存在!", isError = true)
} }
} else { } else {
result.add(target) result.add(target)
} }
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath} 多文件分割 第${lineNum}个文件 ${target.absolutePath}")
} }
return true return true
} }
@ -173,10 +183,13 @@ class SourceFile(text: String) {
if (checkExists) { if (checkExists) {
if (target.exists()) { if (target.exists()) {
result.add(target) result.add(target)
}else{
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath} 解析常规文件 ${target.absolutePath} 不存在!", isError = true)
} }
} else { } else {
result.add(target) result.add(target)
} }
DebugHelper.printLog("搜索资源文件","文件${file.absolutePath} 解析常规文件 ${target.absolutePath}")
} }
if (result.size > 0) { if (result.size > 0) {
result.toTypedArray() result.toTypedArray()

View File

@ -0,0 +1,9 @@
package com.coldmint.rust.core.turret
/**
* 坐标数据
* @property x Int
* @property y Int
* @constructor
*/
data class CoordinateData(val x: Int = 0, val y: Int = 0)

View File

@ -1,10 +0,0 @@
package com.coldmint.rust.core.turret
import java.io.File
/**
* 可安装的炮塔数据类
* @property name String
* @constructor
*/
data class InstallableTurret(val name: String, var x: Int, var y: Int, var imageFile: File? = null)

View File

@ -0,0 +1,10 @@
package com.coldmint.rust.core.turret
import java.io.File
/**
* 炮塔数据类
* @property name String
* @constructor
*/
data class TurretData(val name: String, var x: Int, var y: Int, var imageFile: File? = null)

View File

@ -6,7 +6,9 @@ import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.Drawable.createFromPath import android.graphics.drawable.Drawable.createFromPath
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import com.coldmint.rust.core.R import com.coldmint.rust.core.R
import com.coldmint.rust.core.SourceFile import com.coldmint.rust.core.SourceFile
@ -15,128 +17,40 @@ import com.coldmint.rust.core.SourceFile
* 炮塔安装器 * 炮塔安装器
* 此类用于安装炮塔将炮塔安放到视图上 * 此类用于安装炮塔将炮塔安放到视图上
*/ */
class TurretInstaller( object TurretInstaller {
val parentView: ViewGroup,
val turretManager: TurretManager
) {
private var scale: Int = 1
/** /**
* 设置缩放比例 * 安装全部炮塔到视图
*/ * @param frameLayout FrameLayout
fun setScale(value: Int) {
scale = value
}
/**
* 构造方法使用源文件构造
* @param parentView View
* @param sourceFile SourceFile * @param sourceFile SourceFile
* @constructor
*/ */
constructor(parentView: ViewGroup, sourceFile: SourceFile) : this( fun installerAllTurret(
parentView, viewGroup: ViewGroup,
sourceFile.getTurretManager() sourceFile: SourceFile,
) coordinateChangeListener: (CoordinateData) -> Unit
) {
/** sourceFile.getTurretManager().turretList.forEach {
* 安装所有炮塔到视图容器内 installerTurret(viewGroup, it,coordinateChangeListener)
*/
@SuppressLint("ObjectAnimatorBinding")
fun installAllTurrets() {
val turretList = turretManager.turretList
val size = turretList.size
if (size > 0) {
turretList.forEach {
val imageView = ImageView(parentView.context)
val imageFile = it.imageFile
if (imageFile == null) {
setNoneImage(imageView)
} else {
val bitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
if (bitmap == null) {
setNoneImage(imageView)
} else {
imageView.setImageBitmap(bitmap)
val layoutParams =
ViewGroup.LayoutParams(bitmap.width * scale, bitmap.height * scale)
imageView.layoutParams = layoutParams
}
}
imageView.setOnTouchListener { view, motionEvent ->
if (view == null || motionEvent == null) {
false
}
val x = motionEvent.x
val y = motionEvent.y
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
// val setDown = AnimatorSet()
// setDown.playTogether(
// ObjectAnimator.ofFloat(this, "scaleX", 1f, 1.5f),
// ObjectAnimator.ofFloat(this, "scaleY", 1f, 1.5f),
// ObjectAnimator.ofFloat(this, "alpha", 1f, 0.5f)
// )
// setDown.start()
}
MotionEvent.ACTION_MOVE -> {
view.setX(x + view.getLeft() + view.getTranslationX() - view.getWidth() / 2);
view.setY(y + view.getTop() + view.getTranslationY() - view.getHeight() / 2);
}
MotionEvent.ACTION_UP -> {
// val setUp = AnimatorSet()
// setUp.playTogether(
// ObjectAnimator.ofFloat(this, "scaleX", 1.5f, 1f),
// ObjectAnimator.ofFloat(this, "scaleY", 1.5f, 1f),
// ObjectAnimator.ofFloat(this, "alpha", 0.5f, 1f)
// );
// setUp.start()
}
else -> {
false
}
}
true
}
parentView.addView(imageView)
}
} }
} }
/** /**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp * 安装单个炮塔到视图
* @param frameLayout FrameLayout
* @param sourceFile SourceFile
*/ */
fun px2dip(context: Context, pxValue: Float): Int { fun installerTurret(viewGroup: ViewGroup, turretData: TurretData, coordinateChangeListener: (CoordinateData) -> Unit
val scale = context.resources.displayMetrics.density
return (pxValue / scale + 0.5f).toInt()
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
fun dip2px(context: Context, dpValue: Float): Int {
val scale = context.resources.displayMetrics.density
return (dpValue * scale + 0.5f).toInt()
}
/**
* 设置空白图像(不受缩放限制)
* @param imageView ImageView 图片框
* @param size Int 尺寸
*/
private fun setNoneImage(
imageView: ImageView,
size: Int = dip2px(parentView.context, 30.toFloat())
) { ) {
imageView.setImageResource(R.drawable.image) val turretView = TurretView(viewGroup.context)
//设置默认图像大小 turretView.setTurretData(turretData)
val layoutParams = turretView.setOnTouchListener { view, motionEvent ->
ViewGroup.LayoutParams(size, size) turretView.setTurretX(motionEvent.x.toInt())
imageView.layoutParams = layoutParams turretView.setTurretY(motionEvent.y.toInt())
coordinateChangeListener.invoke(CoordinateData(motionEvent.x.toInt(),motionEvent.y.toInt()))
turretView.invalidate()
true
}
viewGroup.addView(turretView)
} }
} }

View File

@ -13,10 +13,10 @@ import java.io.File
class TurretManager(val sourceFile: SourceFile) { class TurretManager(val sourceFile: SourceFile) {
/** /**
* 可安装的炮塔列表 * 炮塔列表
*/ */
val turretList by lazy { val turretList by lazy {
ArrayList<InstallableTurret>() ArrayList<TurretData>()
} }
init { init {
@ -45,17 +45,17 @@ class TurretManager(val sourceFile: SourceFile) {
if (yData != null) { if (yData != null) {
y = yData.toInt() y = yData.toInt()
} }
val installableTurret = InstallableTurret(name, x, y) val turretData = TurretData(name, x, y)
val fileList = sourceFile.findResourceFilesFromSection("image", it, false) val fileList = sourceFile.findResourceFilesFromSection("image", it, false)
if (!fileList.isNullOrEmpty()) { if (!fileList.isNullOrEmpty()) {
val file = fileList.get(0) val file = fileList.get(0)
installableTurret.imageFile = file turretData.imageFile = file
Log.d("炮塔管理器-$name", file.absolutePath) Log.d("炮塔管理器-$name", "设置炮塔图像"+file.absolutePath)
} else { } else {
installableTurret.imageFile = defaultImageFile turretData.imageFile = defaultImageFile
Log.d("炮塔管理器-$name", "加载默认图像" + defaultImageFile?.absolutePath) Log.d("炮塔管理器-$name", "加载默认图像" + defaultImageFile?.absolutePath)
} }
turretList.add(installableTurret) turretList.add(turretData)
} }
} }
} }

View File

@ -0,0 +1,178 @@
package com.coldmint.rust.core.turret
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.RelativeLayout
import com.coldmint.rust.core.R
/**
* 炮塔画板
* @constructor
*/
class TurretSketchpadView(context: Context, attributeSet: AttributeSet? = null) :
View(context, attributeSet) {
private val debug = "炮塔画板"
private var mainImagePath: String? = null
//计算中心点
private var centreX = 0
private var centreY = 0
//计算绘制点 取图像中点坐标(图像尺寸*缩放比例/2)
private var startX = 0
private var startY = 0
private var endX = 0
private var endY = 0
//单元格宽度
private var cellSize = 10
//设置是否绘制坐标
var drawCoordinate = true
init {
val typedArray =
context.obtainStyledAttributes(attributeSet, R.styleable.turretSketchpadView)
//读取自定义属性
drawCoordinate = typedArray.getBoolean(R.styleable.turretSketchpadView_drawCoordinate, true)
typedArray.recycle()
}
/**
* 设置主要图像
* @param path String
*/
fun setImage(path: String) {
mainImagePath = path
invalidate()
}
/**
* 转换为游戏坐标
* @param androidCoordinateData CoordinateData
* @return CoordinateData
*/
fun toGameCoordinate(androidCoordinateData: CoordinateData): CoordinateData {
val x = (androidCoordinateData.x - centreX) / cellSize
val y = (androidCoordinateData.y - centreY) / cellSize
val game = CoordinateData(x, y)
Log.d(
debug,
"转换坐标,安卓坐标${androidCoordinateData} 游戏坐标${game}"
)
return game
}
/**
* 计算坐标
*/
private fun calculateCoordinate(bitmap: Bitmap) {
//图像
val imageWidth = bitmap.width
val imageHeight = bitmap.height
//计算单元格尺寸
val cellX = width / imageWidth
val cellY = height / imageHeight
cellSize = if (cellX < cellY) {
cellX
} else {
cellY
}
Log.d(
debug,
"计算尺寸\n单元格宽:${cellX} 使用视图宽度${width}除以图像宽度${imageWidth}\n单元格高:${cellY} 使用视图宽度${height}除以图像宽度${imageHeight}\n采用${cellSize}作为视图单元格尺寸"
)
centreX = width / 2
centreY = height / 2
//计算绘制点 取图像中点坐标(图像尺寸*缩放比例/2)
startX = centreX - imageWidth / 2 * cellSize
startY = centreY - imageHeight / 2 * cellSize
endX = startX + imageWidth * cellSize
endY = startY + imageHeight * cellSize
}
/**
* 绘制坐标
* @param canvas Canvas
* @param imageHeight Int
* @param imageWidth Int
*/
private fun drawCoordinate(canvas: Canvas) {
if (drawCoordinate) {
//如果需要绘制
val paint = Paint()
paint.color = Color.RED
//开启描边
paint.style = Paint.Style.STROKE
paint.strokeWidth = 3f
//开始绘制
for (y in startY..endY step cellSize) {
//Y改变x不变
canvas.drawLine(startX.toFloat(), y.toFloat(), endX.toFloat(), y.toFloat(), paint)
}
for (x in startX..endX step cellSize) {
canvas.drawLine(x.toFloat(), startY.toFloat(), x.toFloat(), endY.toFloat(), paint)
}
// canvas.drawCircle(centreX.toFloat(), centreY.toFloat(), 30f, paint)
}
}
/**
* 缩放图像
* @param bitmap Bitmap
* @param size Float
* @return Bitmap
*/
fun scaleBitmap(bitmap: Bitmap, size: Float = cellSize.toFloat()): Bitmap {
//创建新的图像背景
val matrix = Matrix()
matrix.setScale(size, size)
return Bitmap.createBitmap(
bitmap,
0,
0,
bitmap.getWidth(),
bitmap.getHeight(),
matrix,
true
)
}
/**
* 绘制主体图像
*/
private fun drawImage(canvas: Canvas, bitmap: Bitmap) {
val paint = Paint()
val temBitmap = scaleBitmap(bitmap)
canvas.drawBitmap(temBitmap, startX.toFloat(), startY.toFloat(), paint)
temBitmap.recycle()
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (mainImagePath != null && canvas != null) {
val bitmap = BitmapFactory.decodeFile(mainImagePath)
//计算坐标
calculateCoordinate(bitmap)
//设置图像
drawImage(canvas, bitmap)
//设置坐标系(如果需要)
drawCoordinate(canvas)
if (!bitmap!!.isRecycled) {
bitmap.recycle()
}
}
}
}

View File

@ -0,0 +1,94 @@
package com.coldmint.rust.core.turret
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Bitmap.createBitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.util.Log
import android.view.View
import com.coldmint.rust.core.R
/**
* 炮塔视图
* @constructor
*/
class TurretView(context: Context, attributeSet: AttributeSet? = null) :
View(context, attributeSet) {
private val debugKey = "炮塔视图"
private lateinit var turretData: TurretData
private var bitmapW: Int = 0
private var bitmapH: Int = 0
/**
* 设置炮塔数据
* @param turretData TurretData
*/
fun setTurretData(turretData: TurretData) {
this.turretData = turretData
}
/**
* 获取炮塔数据若未初始化返回null
* @return TurretData?
*/
fun getTurretData(): TurretData? {
if (this::turretData.isInitialized) {
return turretData
}
return null
}
/**
* 设置炮塔X
* @param x Int
*/
fun setTurretX(x: Int) {
if (this::turretData.isInitialized) {
turretData.x = x
}
}
/**
* 设置炮塔X
* @param y Int
*/
fun setTurretY(y: Int) {
if (this::turretData.isInitialized) {
turretData.y = y
}
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (this::turretData.isInitialized) {
val paint = Paint()
val bitmap = if (turretData.imageFile == null) {
BitmapFactory.decodeResource(this.resources, R.drawable.image)
} else {
BitmapFactory.decodeFile(turretData.imageFile!!.absolutePath)
}
bitmapW = bitmap.width
bitmapH = bitmap.height
canvas?.drawBitmap(
bitmap,
(turretData.x - bitmapW / 2).toFloat(),
(turretData.y - bitmapH / 2).toFloat(),
paint
)
if (!bitmap.isRecycled) {
bitmap.recycle()
}
} else {
Log.e(debugKey, "未设置炮塔数据,停止绘制。")
}
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--声明样式属性-->
<declare-styleable name="turretSketchpadView">
<!--是否绘制坐标-->
<attr name="drawCoordinate" format="boolean" />
</declare-styleable>
</resources>

View File

@ -36,8 +36,8 @@ dependencies {
implementation 'com.google.android.material:material:1.6.1' implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.4.2' implementation 'androidx.appcompat:appcompat:1.5.0'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

View File

@ -2,4 +2,3 @@ include ':app'
rootProject.name = "铁锈助手" rootProject.name = "铁锈助手"
include ':assistantCoreLibrary' include ':assistantCoreLibrary'
include ':dialog' include ':dialog'
include ':turretsDragView'

View File

@ -1 +0,0 @@
/build

View File

@ -1,40 +0,0 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 32
defaultConfig {
minSdk 21
targetSdk 32
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -1,24 +0,0 @@
package com.coldmint.turretsdragview
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.coldmint.turretsdragview.test", appContext.packageName)
}
}

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.coldmint.turretsdragview">
</manifest>

View File

@ -1,11 +0,0 @@
package com.coldmint.turretsdragview
/**
* 炮塔数据
* @property name String
* @property x Int
* @property y Int
* @constructor
*/
data class TurretData(val name: String, val x: Int, val y: Int)

View File

@ -1,84 +0,0 @@
package com.coldmint.turretsdragview
import android.content.Context
import android.graphics.*
import android.util.Log
import android.view.View
/**
* 炮塔拖拽视图
*/
class TurretsDragView(context: Context) : View(context) {
val key = "炮塔拖拽视图"
//主要位图变量
private var baseBitmap: Bitmap? = null
//画布
private var canvas: Canvas? = null
//画笔
private val paint by lazy {
Paint()
}
//路径与位图之间的映射
val map = HashMap<String, Bitmap>()
/**
* 获取位图
* 优先从映射里读取
* @param path String
* @return Bitmap
*/
fun getBitmap(path: String): Bitmap {
var bitmap = map[path]
if (bitmap == null) {
bitmap = BitmapFactory.decodeFile(path)
map[path] = bitmap
}
return bitmap!!
}
/**
* 设置主体图像
*/
fun setBaseImage(path: String) {
baseBitmap = getBitmap(path)
}
/**
* 炮塔列表数据
*/
private val turretList by lazy {
ArrayList<TurretData>()
}
/**
* 当测量视图
* @param widthMeasureSpec Int
* @param heightMeasureSpec Int
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
/**
* 当绘制视图
* @param canvas Canvas
*/
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
this.canvas = canvas
if (baseBitmap == null) {
Log.e(key, "未设置炮塔主体图像")
throw NullPointerException("未设置炮塔主体图像")
}else{
val matrix = Matrix()
canvas!!.drawBitmap(baseBitmap!!,matrix, paint)
}
}
}

View File

@ -1,17 +0,0 @@
package com.coldmint.turretsdragview
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}