diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2015-02-04 16:02:15 +0900 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2015-02-09 08:12:08 +0100 |
commit | e2d4cfa425a9cecb31ef8aa74722083dca004b3c (patch) | |
tree | b89c56cbdbfdcedd0c18cb7577b3342dbaa88872 /android | |
parent | 48ae33bd8513678c898c5ba692351be2e95a7e83 (diff) |
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
Diffstat (limited to 'android')
6 files changed, 184 insertions, 0 deletions
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 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > + <size android:width="2px" /> + <size android:height="1px" /> + <solid android:color="#000000"/> +</shape>
\ 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"/> + + <org.libreoffice.TextCursorView android:id="@+id/text_cursor_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/text_cursor" + android:visibility="gone"/> + </merge> 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 |