Skip to content

Commit 7d3d3f7

Browse files
committed
Adding JIIX export.
1 parent 9978e95 commit 7d3d3f7

File tree

7 files changed

+168
-20
lines changed

7 files changed

+168
-20
lines changed

samples/offscreen-interactivity/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@
1919
<category android:name="android.intent.category.LAUNCHER" />
2020
</intent-filter>
2121
</activity>
22+
23+
<provider
24+
android:name="androidx.core.content.FileProvider"
25+
android:authorities="${applicationId}.export"
26+
android:exported="false"
27+
android:grantUriPermissions="true">
28+
<meta-data
29+
android:name="android.support.FILE_PROVIDER_PATHS"
30+
android:resource="@xml/file_paths" />
31+
</provider>
2232
</application>
2333

2434
</manifest>

samples/offscreen-interactivity/src/main/java/com/myscript/iink/demo/inksample/ui/InkViewModel.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ class InkViewModel(
105105
val iinkModel: LiveData<String>
106106
get() = _iinkModel
107107

108+
private val _iinkJIIX: MutableLiveData<String> = MutableLiveData()
109+
val iinkJIIX: LiveData<String>
110+
get() = _iinkJIIX
111+
108112
private var offscreenEditor by autoCloseable<OffscreenEditor>()
109113
private var currentPart by autoCloseable<ContentPart>()
110114

@@ -119,7 +123,7 @@ class InkViewModel(
119123
// Maps the data model IDs of the iink offscreen editor to the data model IDs of the application.
120124
private val strokeIdsMapping: MutableMap<String /* id of iink stroke */, String /* id of app stroke */> = mutableMapOf()
121125

122-
private val contentFile: File
126+
val contentFile: File
123127
get() = File(dataDir, "OffscreenEditor.iink")
124128

125129
var displayMetrics: DisplayMetrics? = null
@@ -327,6 +331,19 @@ class InkViewModel(
327331
} ?: emptyList()
328332
} ?: emptyList()
329333
}
334+
_iinkJIIX.value = withContext(defaultDispatcher) {
335+
val engine = engine ?: return@withContext ""
336+
337+
offscreenEditor?.export_(emptyArray(), MimeType.JIIX, engine.createParameterSet().apply {
338+
setBoolean("export.jiix.strokes", false)
339+
setBoolean("export.jiix.bounding-box", false)
340+
setBoolean("export.jiix.glyphs", false)
341+
setBoolean("export.jiix.primitives", false)
342+
setBoolean("export.jiix.text.chars", false)
343+
setBoolean("export.jiix.text.words", false)
344+
345+
})
346+
} ?: ""
330347
_recognitionFeedback.value = _recognitionFeedback.value?.copy(words = adjustedWords)
331348
}
332349
}

samples/offscreen-interactivity/src/main/java/com/myscript/iink/demo/inksample/ui/MainActivity.kt

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@
33
package com.myscript.iink.demo.inksample.ui
44

55
import android.annotation.SuppressLint
6+
import android.content.ClipData
7+
import android.content.ClipboardManager
8+
import android.content.Context
69
import android.os.Bundle
10+
import android.text.method.ScrollingMovementMethod
11+
import android.view.View
712
import android.webkit.WebSettings
813
import android.webkit.WebViewClient
9-
import android.widget.Toast
1014
import androidx.activity.viewModels
1115
import androidx.appcompat.app.AppCompatActivity
16+
import androidx.core.app.ShareCompat
17+
import androidx.core.content.FileProvider
1218
import androidx.core.view.doOnLayout
13-
import androidx.core.view.isVisible
1419
import com.microsoft.device.ink.InkView
1520
import com.myscript.iink.offscreen.demo.databinding.MainActivityBinding
21+
import java.io.File
1622

1723
class MainActivity : AppCompatActivity() {
1824

@@ -47,6 +53,7 @@ class MainActivity : AppCompatActivity() {
4753
inkViewModel.recognitionFeedback.observe(this, ::onRecognitionUpdate)
4854
inkViewModel.iinkModel.observe(this, ::onIInkModelUpdate)
4955
inkViewModel.editorHistoryState.observe(this, ::onUndoRedoStateUpdate)
56+
inkViewModel.iinkJIIX.observe(this, ::onIInkJIIXUpdate)
5057
}
5158

5259
override fun onStart() {
@@ -57,11 +64,47 @@ class MainActivity : AppCompatActivity() {
5764
undoBtn.setOnClickListener { inkViewModel.undo() }
5865
redoBtn.setOnClickListener { inkViewModel.redo() }
5966
clearInkBtn.setOnClickListener { inkViewModel.clearInk() }
67+
exportBtn.setOnClickListener {
68+
inkViewModel.saveInk {
69+
val iinkFile = inkViewModel.contentFile
70+
val exportedFile = File(cacheDir, iinkFile.name)
71+
iinkFile.copyTo(exportedFile, true)
72+
73+
val jiixFile = File(cacheDir, "export.jiix").apply {
74+
delete()
75+
printWriter().use { out ->
76+
out.print(iinkJiix.text)
77+
}
78+
}
79+
80+
val authority = "com.myscript.iink.offscreen.demo.export"
81+
val iinkUri = FileProvider.getUriForFile(this@MainActivity, authority, exportedFile)
82+
val jiixUri = FileProvider.getUriForFile(this@MainActivity, authority, jiixFile)
83+
84+
ShareCompat.IntentBuilder(this@MainActivity)
85+
.setType("*/*")
86+
.addStream(iinkUri)
87+
.addStream(jiixUri)
88+
.startChooser()
89+
}
90+
}
91+
6092
recognitionSwitch.setOnCheckedChangeListener { _, isChecked ->
6193
inkViewModel.toggleRecognition(isVisible = isChecked)
6294
}
6395
iinkModelPreviewSwitch.setOnCheckedChangeListener { _, isChecked ->
64-
iinkModelPreviewLayout.isVisible = isChecked
96+
iinkModelPreviewLayout.visibility = if (isChecked) View.VISIBLE else View.GONE
97+
}
98+
iinkJiixSwitch.setOnCheckedChangeListener { _, isChecked ->
99+
iinkJiixLayout.visibility = if (isChecked) View.VISIBLE else View.GONE
100+
}
101+
iinkJiix.movementMethod = ScrollingMovementMethod()
102+
iinkJiix.setOnLongClickListener {
103+
// Copy the text to the clipboard
104+
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
105+
val clip = ClipData.newPlainText("jiix", iinkJiix.text)
106+
clipboard.setPrimaryClip(clip)
107+
true
65108
}
66109
}
67110
}
@@ -112,6 +155,11 @@ class MainActivity : AppCompatActivity() {
112155
}
113156
}
114157

158+
private fun onIInkJIIXUpdate(jiixExport: String) {
159+
binding.iinkJiix.text = jiixExport
160+
binding.iinkJiix.scrollTo(0, 0)
161+
}
162+
115163
/**
116164
* Listen for strokes from InkView.InputManager
117165
*/
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
2+
3+
<path android:fillColor="@android:color/white" android:pathData="M19,7v2.99s-1.99,0.01 -2,0L17,7h-3s0.01,-1.99 0,-2h3L17,2h2v3h3v2h-3zM16,11L16,8h-3L13,5L5,5c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-8h-3zM5,19l3,-4 2,3 3,-4 4,5L5,19z"/>
4+
5+
</vector>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="800dp"
3+
android:height="800dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M8.71,7.71 L11,5.41V15a1,1 0,0 0,2 0V5.41l2.29,2.3a1,1 0,0 0,1.42 0,1 1,0 0,0 0,-1.42l-4,-4a1,1 0,0 0,-0.33 -0.21,1 1,0 0,0 -0.76,0 1,1 0,0 0,-0.33 0.21l-4,4A1,1 0,1 0,8.71 7.71ZM21,14a1,1 0,0 0,-1 1v4a1,1 0,0 1,-1 1H5a1,1 0,0 1,-1 -1V15a1,1 0,0 0,-2 0v4a3,3 0,0 0,3 3H19a3,3 0,0 0,3 -3V15A1,1 0,0 0,21 14Z"
8+
android:fillColor="#000000"/>
9+
</vector>

samples/offscreen-interactivity/src/main/res/layout/main_activity.xml

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@
5050
android:background="?attr/selectableItemBackgroundBorderless"
5151
android:src="@drawable/outline_delete_forever_24"
5252
android:contentDescription="Clear" />
53+
54+
<ImageView
55+
android:id="@+id/export_btn"
56+
android:layout_width="48dp"
57+
android:layout_height="48dp"
58+
android:padding="12dp"
59+
android:background="?attr/selectableItemBackgroundBorderless"
60+
android:src="@drawable/ic_export"
61+
android:contentDescription="Export" />
5362
</LinearLayout>
5463
</androidx.appcompat.widget.Toolbar>
5564
</com.google.android.material.appbar.AppBarLayout>
@@ -73,23 +82,50 @@
7382
android:layout_width="match_parent"
7483
android:layout_height="match_parent" />
7584

76-
<FrameLayout
77-
android:id="@+id/iink_model_preview_layout"
78-
android:layout_width="@dimen/iink_model_preview_size"
79-
android:layout_height="@dimen/iink_model_preview_size"
85+
<LinearLayout
86+
android:layout_width="wrap_content"
87+
android:layout_height="wrap_content"
8088
android:layout_gravity="top|end"
81-
android:layout_margin="4dp"
82-
android:padding="2dp"
83-
android:background="@drawable/rectangle"
84-
android:backgroundTint="#1E000000"
85-
android:visibility="invisible"
86-
tools:visibility="visible">
87-
88-
<WebView
89-
android:id="@+id/iink_model_preview"
90-
android:layout_width="match_parent"
91-
android:layout_height="match_parent" />
92-
</FrameLayout>
89+
android:orientation="vertical"
90+
android:layout_margin="4dp">
91+
92+
<FrameLayout
93+
android:id="@+id/iink_model_preview_layout"
94+
android:layout_width="@dimen/iink_model_preview_size"
95+
android:layout_height="@dimen/iink_model_preview_size"
96+
android:padding="2dp"
97+
android:background="@drawable/rectangle"
98+
android:visibility="gone"
99+
tools:visibility="visible">
100+
<WebView
101+
android:id="@+id/iink_model_preview"
102+
android:layout_width="match_parent"
103+
android:layout_height="match_parent" />
104+
</FrameLayout>
105+
106+
<LinearLayout
107+
android:id="@+id/iink_jiix_layout"
108+
android:layout_width="@dimen/iink_model_preview_size"
109+
android:layout_height="@dimen/iink_model_preview_size"
110+
android:padding="2dp"
111+
android:background="@drawable/rectangle"
112+
android:orientation="vertical"
113+
android:visibility="gone"
114+
tools:visibility="visible">
115+
116+
<TextView
117+
android:id="@+id/iink_jiix"
118+
android:scrollbars="vertical"
119+
android:layout_width="match_parent"
120+
android:layout_height="0dp"
121+
android:layout_weight="1"
122+
android:padding="4dp"
123+
android:background="@android:color/white"/>
124+
125+
</LinearLayout>
126+
127+
</LinearLayout>
128+
93129
</FrameLayout>
94130

95131
<View
@@ -123,6 +159,18 @@
123159
app:switchPadding="8dp"
124160
android:text="Show iink model"
125161
tools:ignore="HardcodedText" />
162+
163+
<androidx.appcompat.widget.SwitchCompat
164+
android:id="@+id/iink_jiix_switch"
165+
android:layout_width="wrap_content"
166+
android:layout_height="wrap_content"
167+
android:checked="false"
168+
android:layout_marginVertical="16dp"
169+
android:layout_marginHorizontal="16dp"
170+
app:switchPadding="8dp"
171+
android:text="Show iink jiix"
172+
tools:ignore="HardcodedText" />
173+
126174
</LinearLayout>
127175

128176
</LinearLayout>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<paths>
3+
<cache-path name="exports" path="exports/"/>
4+
5+
<!-- We give access to Context. getCacheDir() directory
6+
Used when we need to store a file for intermediate result.
7+
Once our calculations are done it's best to remove the files,
8+
but if we don't the system will remove them when running low.
9+
/data/data/com.myscript.nebo.debug/cache/-->
10+
<cache-path name="tempAppDir" path="/"/>
11+
</paths>

0 commit comments

Comments
 (0)