From e2d4cfa425a9cecb31ef8aa74722083dca004b3c Mon Sep 17 00:00:00 2001 From: Tomaž Vajngerl Date: Wed, 4 Feb 2015 16:02:15 +0900 Subject: android: show text cursor in place suggested by invalid. event Text cursor is a simple line (currently implemented as a drawable and streched), which height is adaptable. It is drawn in a different layer than the document. Change-Id: I40509a866e3a3173e3efcb88e73066565a1619ae --- .../LOAndroid3/res/drawable/text_cursor.xml | 6 ++ .../res/layout/text_selection_handles.xml | 7 ++ .../java/org/libreoffice/LOKitTileProvider.java | 4 ++ .../org/libreoffice/LibreOfficeMainActivity.java | 6 ++ .../src/java/org/libreoffice/TextCursorLayer.java | 82 ++++++++++++++++++++++ .../src/java/org/libreoffice/TextCursorView.java | 79 +++++++++++++++++++++ 6 files changed, 184 insertions(+) create mode 100644 android/experimental/LOAndroid3/res/drawable/text_cursor.xml create mode 100644 android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java create mode 100644 android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java (limited to 'android') diff --git a/android/experimental/LOAndroid3/res/drawable/text_cursor.xml b/android/experimental/LOAndroid3/res/drawable/text_cursor.xml new file mode 100644 index 000000000000..f39e6e8a6d1f --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable/text_cursor.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml index c876b288bc3d..8d8d0148bb0b 100644 --- a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml +++ b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml @@ -26,4 +26,11 @@ android:src="@drawable/handle_end_level" android:visibility="gone" gecko:handleType="end"/> + + + diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java index 48868f9b2e57..60c3e9ce8df7 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java @@ -395,6 +395,10 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection(); textSelection.positionHandle(TextSelectionHandle.HandleType.MIDDLE, underSelection); textSelection.showHandle(TextSelectionHandle.HandleType.MIDDLE); + + TextCursorLayer textCursorLayer = LibreOfficeMainActivity.mAppContext.getTextCursorLayer(); + textCursorLayer.positionCursor(rect); + textCursorLayer.showCursor(); } break; } diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java index 42ffac8f4a8b..56e388968e77 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java @@ -48,6 +48,7 @@ public class LibreOfficeMainActivity extends LOAbout { private DocumentPartViewListAdapter mDocumentPartViewListAdapter; private String mInputFile; private TextSelection mTextSelection; + private TextCursorLayer mTextCursorLayer; public LibreOfficeMainActivity() { super(/*newActivity=*/false); @@ -126,6 +127,7 @@ public class LibreOfficeMainActivity extends LOAbout { } mTextSelection = new TextSelection(mAppContext); + mTextCursorLayer = new TextCursorLayer(mAppContext); mLayerClient = new GeckoLayerClient(this); mLayerClient.setZoomConstraints(new ZoomConstraints(true)); @@ -238,6 +240,10 @@ public class LibreOfficeMainActivity extends LOAbout { return mTextSelection; } + public TextCursorLayer getTextCursorLayer() { + return mTextCursorLayer; + } + private class DocumentPartClickListener implements android.widget.AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java new file mode 100644 index 000000000000..e83a56c30f8d --- /dev/null +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorLayer.java @@ -0,0 +1,82 @@ +package org.libreoffice; + +import android.app.Activity; +import android.graphics.RectF; +import android.util.Log; +import android.view.View; + +import org.mozilla.gecko.TextSelectionHandle; +import org.mozilla.gecko.gfx.Layer; +import org.mozilla.gecko.gfx.LayerView; +import org.mozilla.gecko.util.FloatUtils; + +/** + * The TextCursorLayer is a layer which is responsible for showing the cursor and + * controls its position, height and visibility. + */ +public class TextCursorLayer extends Layer { + private static final String LOGTAG = TextCursorLayer.class.getSimpleName(); + + private final TextCursorView mCursorView; + private float mViewLeft; + private float mViewTop; + private float mViewZoom; + + public TextCursorLayer(Activity context) { + mCursorView = (TextCursorView) context.findViewById(R.id.text_cursor_view); + if (mCursorView == null) { + Log.e(LOGTAG, "Failed to initialize TextCursorLayer - CursorView is null"); + } + } + + @Override + public void draw(final RenderContext context) { + if (FloatUtils.fuzzyEquals(mViewLeft, context.viewport.left) + && FloatUtils.fuzzyEquals(mViewTop, context.viewport.top) + && FloatUtils.fuzzyEquals(mViewZoom, context.zoomFactor)) { + return; + } + + mViewLeft = context.viewport.left; + mViewTop = context.viewport.top; + mViewZoom = context.zoomFactor; + + LOKitShell.getMainHandler().post(new Runnable() { + public void run() { + mCursorView.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor); + } + }); + } + + public void showCursor() { + LOKitShell.getMainHandler().post(new Runnable() { + public void run() { + mCursorView.setVisibility(View.VISIBLE); + + mViewLeft = 0.0f; + mViewTop = 0.0f; + mViewZoom = 0.0f; + LayerView layerView = LOKitShell.getLayerView(); + if (layerView != null) { + layerView.addLayer(TextCursorLayer.this); + } + } + }); + } + + public void hideCursor() { + LOKitShell.getMainHandler().post(new Runnable() { + public void run() { + mCursorView.setVisibility(View.GONE); + } + }); + } + + public void positionCursor(final RectF position) { + LOKitShell.getMainHandler().post(new Runnable() { + public void run() { + mCursorView.changePosition(position); + } + }); + } +} diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java new file mode 100644 index 000000000000..d9e51fcedb93 --- /dev/null +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TextCursorView.java @@ -0,0 +1,79 @@ +package org.libreoffice; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import org.mozilla.gecko.gfx.ImmutableViewportMetrics; +import org.mozilla.gecko.gfx.LayerView; +import org.mozilla.gecko.gfx.RectUtils; + +/** + * Text cursor view responsible to show the cursor drawable on the screen. + */ +public class TextCursorView extends ImageView { + private static final String LOGTAG = TextCursorView.class.getSimpleName(); + + private RectF mPosition; + private RelativeLayout.LayoutParams mLayoutParams; + + private int mLeft; + private int mTop; + + private int mWidth; + private int mHeight; + + public TextCursorView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void changePosition(RectF position) { + LayerView layerView = LOKitShell.getLayerView(); + if (layerView == null) { + Log.e(LOGTAG, "Can't position handle because layerView is null"); + return; + } + + mPosition = position; + + mWidth = Math.round(position.width()); + mHeight = Math.round(position.height()); + + ImmutableViewportMetrics metrics = layerView.getViewportMetrics(); + repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor); + } + + public void repositionWithViewport(float x, float y, float zoom) { + RectF scaled = RectUtils.scale(mPosition, zoom); + + mLeft = Math.round(scaled.centerX() - x); + mTop = Math.round(scaled.centerY() - y); + + setScaleY(scaled.height()); + + setLayoutPosition(); + } + + private void setLayoutPosition() { + if (mLayoutParams == null) { + mLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams(); + // Set negative right/bottom margins so that the handles can be dragged outside of + // the content area (if they are dragged to the left/top, the dyanmic margins set + // below will take care of that). + mLayoutParams.rightMargin = 0 - mWidth; + mLayoutParams.bottomMargin = 0 - mHeight; + } + + mLayoutParams.leftMargin = mLeft; + mLayoutParams.topMargin = mTop; + + setLayoutParams(mLayoutParams); + } +} \ No newline at end of file -- cgit