android: add cut, copy, paste support to document viewer.

Change-Id: I85c3a602ab7e98272a193c392bf7bcfd1050dc90
Reviewed-on: https://gerrit.libreoffice.org/74127
Reviewed-by: Jan Holesovsky <kendy@collabora.com>
Tested-by: Jan Holesovsky <kendy@collabora.com>
This commit is contained in:
kaishu-sahu 2019-06-17 06:00:00 +05:30 committed by Jan Holesovsky
parent f5a67c696d
commit 73f839164a
3 changed files with 123 additions and 34 deletions

View file

@ -332,4 +332,25 @@ Java_org_libreoffice_androidlib_LOActivity_saveAs(JNIEnv *env, jobject instance,
env->ReleaseStringUTFChars(fileUri_, fileUri);
env->ReleaseStringUTFChars(format_, format);
}
extern "C"
JNIEXPORT jstring JNICALL
Java_org_libreoffice_androidlib_LOActivity_getTextSelection(JNIEnv *env, jobject instance) {
return env->NewStringUTF(getLOKDocument()->getTextSelection("text/plain;charset=utf-8"));
}
extern "C"
JNIEXPORT void JNICALL
Java_org_libreoffice_androidlib_LOActivity_paste(JNIEnv *env, jobject instance, jstring mimeType_,
jstring data_) {
const char *mimeType = env->GetStringUTFChars(mimeType_, 0);
const char *data = env->GetStringUTFChars(data_, 0);
const size_t nSize = env->GetStringLength(data_);
getLOKDocument()->paste(mimeType, data, nSize);
env->ReleaseStringUTFChars(mimeType_, mimeType);
env->ReleaseStringUTFChars(data_, data);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -10,6 +10,9 @@
package org.libreoffice.androidlib;
import android.Manifest;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
@ -23,6 +26,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
@ -83,6 +87,12 @@ public class LOActivity extends AppCompatActivity {
private boolean isDocEditable = false;
private boolean isDocDebuggable = BuildConfig.DEBUG;
private ClipboardManager clipboardManager;
private ClipData clipData;
private Thread nativeMsgThread;
private Handler nativeHandler;
private Looper nativeLooper;
private ValueCallback<Uri[]> valueCallback;
public static final int REQUEST_SELECT_FILE = 555;
@ -282,6 +292,18 @@ public class LOActivity extends AppCompatActivity {
mainHandler = new Handler(getMainLooper());
clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
nativeMsgThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
nativeLooper = Looper.myLooper();
nativeHandler = new Handler(nativeLooper);
Looper.loop();
}
});
nativeMsgThread.start();
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
@ -406,6 +428,7 @@ public class LOActivity extends AppCompatActivity {
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy() - we know we are leaving the document");
nativeLooper.quit();
postMobileMessageNative("BYE");
}
@ -497,20 +520,62 @@ public class LOActivity extends AppCompatActivity {
}
/**
* return true to pass the message to the native part and false to block the message
* return true to pass the message to the native part or false to block the message
*/
boolean interceptMsgFromWebView(String message) {
if (message.equals("PRINT")) {
mainHandler.post(new Runnable() {
@Override
public void run() {
initiatePrint();
switch (message) {
case "PRINT":
mainHandler.post(new Runnable() {
@Override
public void run() {
LOActivity.this.initiatePrint();
}
});
return false;
case "SLIDESHOW":
initiateSlideShow();
return false;
case "uno .uno:Paste":
clipData = clipboardManager.getPrimaryClip();
if (clipData != null) {
if (clipData.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
final ClipData.Item clipItem = clipData.getItemAt(0);
nativeHandler.post(new Runnable() {
@Override
public void run() {
LOActivity.this.paste("text/plain;charset=utf-16", clipItem.getText().toString());
}
});
}
return false;
}
});
return false;
} else if (message.equals("SLIDESHOW")) {
initiateSlideShow();
return false;
break;
case "uno .uno:Copy": {
nativeHandler.post(new Runnable() {
@Override
public void run() {
String tempSelectedText = LOActivity.this.getTextSelection();
if (!tempSelectedText.equals("")) {
clipData = ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, tempSelectedText);
clipboardManager.setPrimaryClip(clipData);
}
}
});
break;
}
case "uno .uno:Cut": {
nativeHandler.post(new Runnable() {
@Override
public void run() {
String tempSelectedText = LOActivity.this.getTextSelection();
if (!tempSelectedText.equals("")) {
clipData = ClipData.newPlainText(ClipDescription.MIMETYPE_TEXT_PLAIN, tempSelectedText);
clipboardManager.setPrimaryClip(clipData);
}
}
});
break;
}
}
return true;
}
@ -526,34 +591,37 @@ public class LOActivity extends AppCompatActivity {
.setCancelable(false)
.setView(R.layout.lolib_dialog_loading)
.create();
new AsyncTask<Void, Void, String>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
slideShowProgress.show();
}
nativeHandler.post(new Runnable() {
@Override
protected String doInBackground(Void... voids) {
public void run() {
LOActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
slideShowProgress.show();
}
});
Log.v(TAG, "saving svg for slideshow by " + Thread.currentThread().getName());
String slideShowFileUri = new File(getCacheDir(), "slideShow.svg").toURI().toString();
saveAs(slideShowFileUri, "svg");
return slideShowFileUri;
final String slideShowFileUri = new File(LOActivity.this.getCacheDir(), "slideShow.svg").toURI().toString();
LOActivity.this.saveAs(slideShowFileUri, "svg");
LOActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
slideShowProgress.dismiss();
Intent slideShowActIntent = new Intent(LOActivity.this, SlideShowActivity.class);
slideShowActIntent.putExtra(SlideShowActivity.SVG_URI_KEY, slideShowFileUri);
LOActivity.this.startActivity(slideShowActIntent);
}
});
}
@Override
protected void onPostExecute(String slideShowFileUri) {
super.onPostExecute(slideShowFileUri);
slideShowProgress.dismiss();
Intent slideShowActIntent = new Intent(LOActivity.this, SlideShowActivity.class);
slideShowActIntent.putExtra(SlideShowActivity.SVG_URI_KEY, slideShowFileUri);
startActivity(slideShowActIntent);
}
}.execute();
});
}
public native void saveAs(String fileUri, String format);
public native String getTextSelection();
public native void paste(String mimeType, String data);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -36,7 +36,7 @@ L.Control.ContextToolbar = L.Control.extend({
},
_initLayout: function () {
if (window.ThisIsTheiOSApp)
if (window.ThisIsTheiOSApp || window.ThisIsTheAndroidApp)
this._container = L.DomUtil.create('div', 'loleaflet-ios-context-toolbar');
else
this._container = L.DomUtil.create('div', 'loleaflet-context-toolbar');
@ -47,7 +47,7 @@ L.Control.ContextToolbar = L.Control.extend({
stopEvents = 'touchstart touchmove touchend mousedown mousemove mouseout mouseover mouseup mousewheel click scroll',
container;
if (window.ThisIsTheiOSApp)
if (window.ThisIsTheiOSApp || window.ThisIsTheAndroidApp)
container = L.DomUtil.create('table', 'loleaflet-ios-context-table', this._container);
else
container = L.DomUtil.create('table', 'loleaflet-context-table', this._container);
@ -55,7 +55,7 @@ L.Control.ContextToolbar = L.Control.extend({
var tbody = L.DomUtil.create('tbody', '', container),
tr = L.DomUtil.create('tr', '', tbody);
if (window.ThisIsTheiOSApp) {
if (window.ThisIsTheiOSApp || window.ThisIsTheAndroidApp) {
this._leftroundedend = L.DomUtil.create(tagTd, 'loleaflet-ios-context-button loleaflet-ios-context-left', tr);
this._cut = L.DomUtil.create(tagTd, 'loleaflet-ios-context-button loleaflet-ios-context-first-and-middle-entry loleaflet-ios-context-cut', tr);
this._cut.innerHTML = _UNO('.uno:Cut');