Skip to content

Commit e025d43

Browse files
authored
Merge pull request #4 from Knowre-Dev/feature/candidate
Feature/candidate
2 parents 2b693b7 + 52f4348 commit e025d43

32 files changed

Lines changed: 825 additions & 309 deletions

app/src/main/java/com/knowre/android/kal/MainActivity.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import androidx.navigation.findNavController
88
import androidx.navigation.ui.AppBarConfiguration
99
import androidx.navigation.ui.navigateUp
1010
import androidx.navigation.ui.setupActionBarWithNavController
11-
import com.google.android.material.snackbar.Snackbar
1211
import com.knowre.android.kal.databinding.ActivityMainBinding
1312

1413
class MainActivity : AppCompatActivity() {
@@ -27,10 +26,6 @@ class MainActivity : AppCompatActivity() {
2726
val navController = findNavController(R.id.nav_host_fragment_content_main)
2827
appBarConfiguration = AppBarConfiguration(navController.graph)
2928
setupActionBarWithNavController(navController, appBarConfiguration)
30-
31-
binding.fab.setOnClickListener { view ->
32-
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show()
33-
}
3429
}
3530

3631
override fun onCreateOptionsMenu(menu: Menu): Boolean {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.knowre.android.kal.myscript
2+
3+
4+
internal sealed class Candidate {
5+
6+
class Data(val itemId: String, val label: String) : Candidate()
7+
8+
class Exit() : Candidate()
9+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.knowre.android.kal.myscript
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.recyclerview.widget.RecyclerView
6+
import com.knowre.android.kal.databinding.ViewCandidateItemBinding
7+
8+
9+
internal class CandidateAdapter(
10+
private val onCandidateClicked: (Candidate.Data) -> Unit,
11+
private val onExitClicked: () -> Unit
12+
) : RecyclerView.Adapter<CandidateViewHolder>() {
13+
14+
private var candidates = listOf<Candidate>()
15+
16+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CandidateViewHolder {
17+
return CandidateViewHolder.newInstance(parent,
18+
onCandidateClicked = {
19+
clear()
20+
onCandidateClicked(it)
21+
},
22+
onExitClicked = {
23+
clear()
24+
onExitClicked()
25+
}
26+
)
27+
}
28+
29+
override fun onBindViewHolder(holder: CandidateViewHolder, position: Int) {
30+
holder.bind(candidates[position])
31+
}
32+
33+
override fun getItemCount() = candidates.size
34+
35+
fun setCandidates(candidates: List<Candidate>) {
36+
this.candidates = candidates
37+
.toMutableList()
38+
.apply { if (isNotEmpty()) add(Candidate.Exit()) }
39+
.also { notifyDataSetChanged() }
40+
}
41+
42+
fun clear() {
43+
this.candidates = listOf()
44+
notifyDataSetChanged()
45+
}
46+
}
47+
48+
internal class CandidateViewHolder(
49+
private val binding: ViewCandidateItemBinding
50+
) : RecyclerView.ViewHolder(binding.root) {
51+
52+
private lateinit var candidate: Candidate
53+
54+
fun bind(candidate: Candidate) {
55+
this.candidate = candidate
56+
when (candidate) {
57+
is Candidate.Data -> binding.candidateText.text = candidate.label
58+
is Candidate.Exit -> {
59+
binding.candidateText.text = "X"
60+
}
61+
}
62+
}
63+
64+
companion object {
65+
fun newInstance(
66+
parent: ViewGroup,
67+
onCandidateClicked: (Candidate.Data) -> Unit,
68+
onExitClicked: () -> Unit
69+
): CandidateViewHolder {
70+
return CandidateViewHolder(ViewCandidateItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)).apply {
71+
binding.root.setOnClickListener {
72+
if (candidate is Candidate.Data) {
73+
onCandidateClicked(candidate as Candidate.Data)
74+
} else {
75+
onExitClicked()
76+
}
77+
}
78+
}
79+
}
80+
}
81+
}

app/src/main/java/com/knowre/android/kal/myscript/MyScriptPadView.kt

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,24 @@ package com.knowre.android.kal.myscript
22

33
import android.content.Context
44
import android.content.res.AssetManager
5+
import android.content.res.ColorStateList
6+
import android.content.res.Resources
7+
import android.graphics.Color
58
import android.util.AttributeSet
69
import android.util.Log
10+
import android.util.TypedValue
711
import android.view.LayoutInflater
812
import android.widget.FrameLayout
13+
import android.widget.Toast
14+
import androidx.recyclerview.widget.LinearLayoutManager
15+
import com.google.android.material.shape.MaterialShapeDrawable
16+
import com.google.android.material.shape.ShapeAppearanceModel
917
import com.knowre.android.kal.databinding.ViewMyscriptPadBinding
10-
import com.knowre.android.myscript.iink.FolderProvider
1118
import com.knowre.android.myscript.iink.MyScriptApi
12-
import com.knowre.android.myscript.iink.MyScriptAssetResource
1319
import com.knowre.android.myscript.iink.MyScriptInitializer
1420
import com.knowre.android.myscript.iink.MyScriptInterpretListener
1521
import com.knowre.android.myscript.iink.ToolFunction
1622
import com.knowre.android.myscript.iink.ToolType
17-
import com.knowre.android.myscript.iink.certificate.MyCertificate
1823
import com.myscript.iink.Editor
1924
import com.myscript.iink.EditorError
2025
import kotlinx.coroutines.MainScope
@@ -32,65 +37,84 @@ internal class MyScriptPadView constructor(
3237

3338
private val mainScope = MainScope()
3439

35-
private lateinit var myscript: MyScriptApi
40+
private lateinit var myScript: MyScriptApi
41+
42+
private val candidateAdapter = CandidateAdapter(
43+
onCandidateClicked = { candidate -> },
44+
onExitClicked = {}
45+
)
3646

3747
init {
38-
MyScriptInitializer(
39-
certificate = MyCertificate.getBytes(),
40-
editorView = binding.myScript.editorView,
41-
context = context,
42-
folders = FolderProvider(context),
43-
assetResource = MyScriptAssetResource(context),
44-
scope = mainScope
45-
)
46-
.setGeneralConfiguration()
47-
.setMathConfiguration()
48-
.initialize {
49-
myscript = it.apply {
50-
listener = object : MyScriptInterpretListener {
51-
override fun onInterpreted(interpreted: String) {
52-
binding.latex.text = interpreted
53-
mainScope.launch {
54-
binding.redo.isEnabled = myscript.canRedo
55-
binding.undo.isEnabled = myscript.canUndo
56-
}
57-
}
58-
59-
override fun onError(editor: Editor, blockId: String, error: EditorError, message: String) {
60-
Log.d("MY_SCRIPT_ERROR", "$error with message $message")
61-
}
62-
}
63-
}
48+
initializeMyScript()
49+
initializeRecyclerView()
50+
initializeToolsListener()
51+
}
52+
53+
override fun onDetachedFromWindow() {
54+
super.onDetachedFromWindow()
55+
mainScope.cancel()
56+
}
57+
58+
private fun initializeMyScript() {
59+
mainScope.launch {
60+
myScript = MyScriptInitializer(
61+
myScriptView = binding.myScriptView,
62+
context = context,
63+
scope = mainScope
64+
)
65+
.initialize()
66+
.apply { addListener(interpretListener) }
67+
.apply { isAutoConvertEnabled = false }
68+
}
69+
}
70+
71+
private fun initializeRecyclerView() {
72+
with(binding.candidate) {
73+
adapter = candidateAdapter
74+
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
75+
background = MaterialShapeDrawable(
76+
ShapeAppearanceModel.Builder()
77+
.setAllCornerSizes(8F.dp)
78+
.build()
79+
).apply {
80+
tintList = ColorStateList.valueOf(Color.parseColor("#FFFFFF"))
81+
strokeWidth = 1F.dp
82+
strokeColor = ColorStateList.valueOf(Color.parseColor("#CFD8DC"))
83+
elevation = 4F.dp
6484
}
85+
}
86+
}
6587

88+
private fun initializeToolsListener() {
6689
binding.redo.isEnabled = false
6790
binding.undo.isEnabled = false
6891

69-
binding.convert.setOnClickListener { myscript.convert() }
70-
binding.deleteAll.setOnClickListener { myscript.eraseAll() }
92+
binding.deleteAll.setOnClickListener { myScript.eraseAll() }
7193
binding.digitOnlyGrammar.setOnClickListener {
72-
myscript.loadMathGrammar("n_digit_exp", context.assets.toByteArray("n_digit_exp.res"))
94+
myScript.loadMathGrammar("n_digit_exp", context.assets.toByteArray("n_digit_exp.res"))
7395
}
7496

7597
binding.defaultGrammar.setOnClickListener {
7698
//TODO
7799
}
78100

79101
binding.red.setOnClickListener {
80-
myscript.penColor = 0xFF0000
102+
myScript.penColor = 0xFF0000
81103
}
82104

83105
binding.blue.setOnClickListener {
84-
myscript.penColor = 0x0000FF
106+
myScript.penColor = 0x0000FF
85107
}
86108

87109
binding.black.setOnClickListener {
88-
myscript.penColor = 0x000000
110+
myScript.penColor = 0x000000
89111
}
90112

113+
binding.convert.setOnClickListener { myScript.convert() }
114+
91115
binding.penSwitch.setOnCheckedChangeListener { _, isChecked ->
92116
binding.eraserSwitch.isChecked = false
93-
myscript.tool = if (isChecked) {
117+
myScript.tool = if (isChecked) {
94118
MyScriptApi.Tool(
95119
toolType = ToolType.PEN,
96120
toolFunction = ToolFunction.DRAWING
@@ -104,32 +128,60 @@ internal class MyScriptPadView constructor(
104128
}
105129

106130
binding.convertSwitch.setOnCheckedChangeListener { _, isChecked ->
107-
myscript.isAutoConvertEnabled = isChecked
131+
myScript.isAutoConvertEnabled = isChecked
108132
}
109133

110134
binding.eraserSwitch.setOnCheckedChangeListener { _, isChecked ->
111135
val toolType = if (binding.penSwitch.isChecked) ToolType.PEN else ToolType.HAND
112136
if (isChecked) {
113-
myscript.tool = MyScriptApi.Tool(toolType, ToolFunction.ERASING)
137+
myScript.tool = MyScriptApi.Tool(toolType, ToolFunction.ERASING)
114138
} else {
115-
myscript.tool = MyScriptApi.Tool(toolType, ToolFunction.DRAWING)
139+
myScript.tool = MyScriptApi.Tool(toolType, ToolFunction.DRAWING)
116140
}
117141
}
118142

119143
binding.redo.setOnClickListener {
120-
myscript.redo()
144+
myScript.redo()
121145
}
122146

123147
binding.undo.setOnClickListener {
124-
myscript.undo()
148+
myScript.undo()
125149
}
150+
151+
binding.candidateSwitch.setOnCheckedChangeListener { _, isChecked -> }
126152
}
127153

128-
override fun onDetachedFromWindow() {
129-
super.onDetachedFromWindow()
130-
mainScope.cancel()
154+
private val interpretListener: MyScriptInterpretListener
155+
get() = object : MyScriptInterpretListener {
156+
override fun onInterpreted(interpreted: String) {
157+
binding.latex.text = interpreted
158+
binding.redo.isEnabled = myScript.canRedo
159+
binding.undo.isEnabled = myScript.canUndo
160+
}
161+
162+
override fun onInterpretError(editor: Editor, blockId: String, error: EditorError, message: String) {
163+
Log.d("MY_SCRIPT_ERROR", "$error with message $message")
164+
}
165+
166+
override fun onImportError() {
167+
Toast
168+
.makeText(context, "해당 문자로는 변경이 불가능합니다.", Toast.LENGTH_SHORT)
169+
.show()
170+
}
171+
}
172+
173+
private fun showNoCandidateAvailable() {
174+
Toast
175+
.makeText(context, "No candidates available.", Toast.LENGTH_SHORT)
176+
.show()
131177
}
132178

133179
private fun AssetManager.toByteArray(fileName: String) = open(fileName).use { it.readBytes() }
134180

181+
private val Number.dp: Float
182+
get() = TypedValue.applyDimension(
183+
TypedValue.COMPLEX_UNIT_DIP,
184+
toFloat(),
185+
Resources.getSystem().displayMetrics
186+
)
135187
}

app/src/main/res/layout/activity_main.xml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,6 @@
2020

2121
</com.google.android.material.appbar.AppBarLayout>
2222

23-
<com.google.android.material.floatingactionbutton.FloatingActionButton
24-
android:id="@+id/fab"
25-
android:layout_width="wrap_content"
26-
android:layout_height="wrap_content"
27-
android:layout_marginBottom="16dp"
28-
android:layout_marginEnd="@dimen/fab_margin"
29-
android:layout_gravity="bottom|end"
30-
app:srcCompat="@android:drawable/ic_dialog_email" />
31-
3223
<include layout="@layout/content_main" />
3324

3425
</androidx.coordinatorlayout.widget.CoordinatorLayout>

app/src/main/res/layout/fragment_first.xml

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,17 @@
1010
android:id="@+id/button_first"
1111
android:layout_width="wrap_content"
1212
android:layout_height="wrap_content"
13-
android:layout_marginBottom="30dp"
13+
android:layout_marginTop="50dp"
1414
android:text="@string/next"
15-
app:layout_constraintBottom_toBottomOf="parent"
15+
app:layout_constraintTop_toTopOf="parent"
1616
app:layout_constraintEnd_toEndOf="parent"
1717
app:layout_constraintStart_toStartOf="parent" />
1818

19-
20-
<TextView
21-
android:id="@+id/textview_first"
22-
android:layout_width="wrap_content"
23-
android:layout_height="wrap_content"
24-
android:layout_marginTop="50dp"
25-
android:background="#ffff00"
26-
android:text="@string/hello_first_fragment"
27-
app:layout_constraintEnd_toEndOf="parent"
28-
app:layout_constraintStart_toStartOf="parent"
29-
app:layout_constraintTop_toTopOf="parent" />
30-
3119
<com.knowre.android.kal.myscript.MyScriptPadView
3220
android:id="@+id/my_script_pad"
3321
android:layout_width="match_parent"
3422
android:layout_height="400dp"
35-
android:layout_marginTop="100dp"
36-
android:background="#44333345"
3723
app:layout_constraintEnd_toEndOf="parent"
3824
app:layout_constraintStart_toStartOf="parent"
39-
app:layout_constraintTop_toTopOf="parent" />
25+
app:layout_constraintBottom_toBottomOf="parent"/>
4026
</androidx.constraintlayout.widget.ConstraintLayout>

0 commit comments

Comments
 (0)