diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2015-01-29 11:26:24 +0900 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2015-02-09 08:09:28 +0100 |
commit | aecce900af9e9d216cd1039c775556b6ff683ce6 (patch) | |
tree | a4d454996252a04f7bd344bdd0bd53b24be9fea6 /android | |
parent | 2a63d8d7adc7ac659ff21af982deabcd6cb7a56a (diff) |
android: integrate text selection handles from Fennec
Integrate text selection handles from Fennec and insert middle
handle when a cursor invalidation event is recieved from LO.
Change-Id: I6ba31d46bf89555bdbca9ce4be666039e8bc9041
Diffstat (limited to 'android')
19 files changed, 441 insertions, 4 deletions
diff --git a/android/experimental/LOAndroid3/res/drawable-hdpi/handle_end.png b/android/experimental/LOAndroid3/res/drawable-hdpi/handle_end.png Binary files differnew file mode 100644 index 000000000000..d5e204429ef3 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable-hdpi/handle_end.png diff --git a/android/experimental/LOAndroid3/res/drawable-hdpi/handle_middle.png b/android/experimental/LOAndroid3/res/drawable-hdpi/handle_middle.png Binary files differnew file mode 100644 index 000000000000..5dcee14f7a70 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable-hdpi/handle_middle.png diff --git a/android/experimental/LOAndroid3/res/drawable-hdpi/handle_start.png b/android/experimental/LOAndroid3/res/drawable-hdpi/handle_start.png Binary files differnew file mode 100644 index 000000000000..b6a8ce79e942 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable-hdpi/handle_start.png diff --git a/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_end.png b/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_end.png Binary files differnew file mode 100644 index 000000000000..c83b7b603765 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_end.png diff --git a/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_middle.png b/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_middle.png Binary files differnew file mode 100644 index 000000000000..2a1774ff98a5 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_middle.png diff --git a/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_start.png b/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_start.png Binary files differnew file mode 100644 index 000000000000..9af76544812c --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable-xhdpi/handle_start.png diff --git a/android/experimental/LOAndroid3/res/drawable/handle_end.png b/android/experimental/LOAndroid3/res/drawable/handle_end.png Binary files differnew file mode 100644 index 000000000000..32b77dfa6e26 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable/handle_end.png diff --git a/android/experimental/LOAndroid3/res/drawable/handle_middle.png b/android/experimental/LOAndroid3/res/drawable/handle_middle.png Binary files differnew file mode 100644 index 000000000000..751eb898b136 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable/handle_middle.png diff --git a/android/experimental/LOAndroid3/res/drawable/handle_start.png b/android/experimental/LOAndroid3/res/drawable/handle_start.png Binary files differnew file mode 100644 index 000000000000..cf12a0dcdcf3 --- /dev/null +++ b/android/experimental/LOAndroid3/res/drawable/handle_start.png diff --git a/android/experimental/LOAndroid3/res/layout/activity_main.xml b/android/experimental/LOAndroid3/res/layout/activity_main.xml index 1b1bb0779b7e..e9a946f6b9dd 100644 --- a/android/experimental/LOAndroid3/res/layout/activity_main.xml +++ b/android/experimental/LOAndroid3/res/layout/activity_main.xml @@ -22,6 +22,9 @@ android:id="@+id/layer_view" android:layout_width="fill_parent" android:layout_height="fill_parent"/> + + <include layout="@layout/text_selection_handles"/> + </RelativeLayout> <RelativeLayout diff --git a/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml new file mode 100644 index 000000000000..1f0d8165729a --- /dev/null +++ b/android/experimental/LOAndroid3/res/layout/text_selection_handles.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:gecko="http://schemas.android.com/apk/res-auto"> + + <org.mozilla.gecko.TextSelectionHandle android:id="@+id/start_handle" + android:layout_width="@dimen/text_selection_handle_width" + android:layout_height="@dimen/text_selection_handle_height" + android:src="@drawable/handle_start" + android:visibility="gone" + gecko:handleType="start"/> + + <org.mozilla.gecko.TextSelectionHandle android:id="@+id/middle_handle" + android:layout_width="@dimen/text_selection_handle_width" + android:layout_height="@dimen/text_selection_handle_height" + android:src="@drawable/handle_middle" + android:visibility="gone" + gecko:handleType="middle"/> + + <org.mozilla.gecko.TextSelectionHandle android:id="@+id/end_handle" + android:layout_width="@dimen/text_selection_handle_width" + android:layout_height="@dimen/text_selection_handle_height" + android:src="@drawable/handle_end" + android:visibility="gone" + gecko:handleType="end"/> +</merge> diff --git a/android/experimental/LOAndroid3/res/values/attrs.xml b/android/experimental/LOAndroid3/res/values/attrs.xml new file mode 100644 index 000000000000..ed7397891d97 --- /dev/null +++ b/android/experimental/LOAndroid3/res/values/attrs.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<resources> + + <declare-styleable name="TextSelectionHandle"> + <attr name="handleType"> + <flag name="start" value="0x01"/> + <flag name="middle" value="0x02"/> + <flag name="end" value="0x03"/> + </attr> + </declare-styleable> + +</resources> + diff --git a/android/experimental/LOAndroid3/res/values/dimens.xml b/android/experimental/LOAndroid3/res/values/dimens.xml index 47c82246738c..1e5d7716f192 100644 --- a/android/experimental/LOAndroid3/res/values/dimens.xml +++ b/android/experimental/LOAndroid3/res/values/dimens.xml @@ -2,4 +2,7 @@ <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> + <dimen name="text_selection_handle_width">30dp</dimen> + <dimen name="text_selection_handle_height">44dp</dimen> + <dimen name="text_selection_handle_shadow">2dp</dimen> </resources> diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java index c8bcc23d76a3..5cb8f319964f 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java @@ -168,8 +168,6 @@ public class LOKitThread extends Thread implements TileProvider.TileInvalidation private void touch(String touchType, MotionEvent motionEvent, PointF mDocumentTouchCoordinate) { LibreOfficeMainActivity.mAppContext.showSoftKeyboard(); - float x = motionEvent.getX(); - float y = motionEvent.getY(); mTileProvider.mouseButtonDown(mDocumentTouchCoordinate); } diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java index 3e3412a74984..553945033274 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java @@ -10,6 +10,7 @@ import org.libreoffice.kit.DirectBufferAllocator; import org.libreoffice.kit.Document; import org.libreoffice.kit.LibreOfficeKit; import org.libreoffice.kit.Office; +import org.mozilla.gecko.TextSelection; import org.mozilla.gecko.gfx.BufferedCairoImage; import org.mozilla.gecko.gfx.CairoImage; import org.mozilla.gecko.gfx.GeckoLayerClient; @@ -303,6 +304,11 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback private void mouseButton(int type, PointF inDocument) { int x = (int) pixelToTwip(inDocument.x, mDPI); int y = (int) pixelToTwip(inDocument.y, mDPI); + + TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection(); + textSelection.positionHandle("MIDDLE", new RectF(inDocument.x, inDocument.y, inDocument.x, inDocument.y)); + textSelection.showHandle("MIDDLE"); + mDocument.postMouseEvent(type, x, y); } @@ -376,9 +382,12 @@ public class LOKitTileProvider implements TileProvider, Document.MessageCallback break; } case Document.CALLBACK_INVALIDATE_VISIBLE_CURSOR: { + Log.i(LOGTAG, "Invalidate visible cursor: " + payload); RectF rect = convertCallbackMessageStringToRectF(payload); if (rect != null) { - //tileInvalidationCallback.invalidate(rect); + TextSelection textSelection = LibreOfficeMainActivity.mAppContext.getTextSelection(); + textSelection.positionHandle("MIDDLE", rect); + textSelection.showHandle("MIDDLE"); } break; } diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java index bca8230d2458..362fb786623e 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java @@ -20,6 +20,8 @@ import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; +import org.mozilla.gecko.TextSelection; +import org.mozilla.gecko.TextSelectionHandle; import org.mozilla.gecko.ZoomConstraints; import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.LayerView; @@ -45,6 +47,7 @@ public class LibreOfficeMainActivity extends LOAbout { private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>(); private DocumentPartViewListAdapter mDocumentPartViewListAdapter; private String mInputFile; + private TextSelection mTextSelection; public LibreOfficeMainActivity() { super(/*newActivity=*/false); @@ -124,6 +127,12 @@ public class LibreOfficeMainActivity extends LOAbout { sLOKitThread.clearQueue(); } + TextSelectionHandle startHandle = (TextSelectionHandle) findViewById(R.id.start_handle); + TextSelectionHandle middleHandle = (TextSelectionHandle) findViewById(R.id.middle_handle); + TextSelectionHandle endHandle = (TextSelectionHandle) findViewById(R.id.end_handle); + + mTextSelection = new TextSelection(startHandle, middleHandle, endHandle); + mLayerClient = new GeckoLayerClient(this); mLayerClient.setZoomConstraints(new ZoomConstraints(true)); LayerView layerView = (LayerView) findViewById(R.id.layer_view); @@ -231,6 +240,10 @@ public class LibreOfficeMainActivity extends LOAbout { alertDialog.show(); } + public TextSelection getTextSelection() { + return mTextSelection; + } + 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/ViewFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java index c26ad222e0d9..68f88d990103 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ViewFactory.java @@ -6,11 +6,13 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import org.mozilla.gecko.TextSelectionHandle; import org.mozilla.gecko.gfx.LayerView; public class ViewFactory implements LayoutInflater.Factory { private static final String LOGTAG = ViewFactory.class.getSimpleName(); private static final String LAYER_VIEW_ID = "org.mozilla.gecko.gfx.LayerView"; + private static final String TEXT_SELECTION_HANDLE_ID = "org.mozilla.gecko.TextSelectionHandle"; private static final ViewFactory INSTANCE = new ViewFactory(); private ViewFactory() { @@ -25,8 +27,10 @@ public class ViewFactory implements LayoutInflater.Factory { if (name.equals(LAYER_VIEW_ID)) { Log.i(LOGTAG, "Creating custom Gecko view: " + name); return new LayerView(context, attrs); + } else if (name.equals(TEXT_SELECTION_HANDLE_ID)) { + Log.i(LOGTAG, "Creating custom Gecko view: " + name); + return new TextSelectionHandle(context, attrs); } - return null; } }
\ No newline at end of file diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelection.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelection.java new file mode 100644 index 000000000000..f09e93a9dbdb --- /dev/null +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelection.java @@ -0,0 +1,191 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import android.graphics.RectF; +import android.util.Log; +import android.view.View; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.libreoffice.LOKitShell; +import org.libreoffice.LibreOfficeMainActivity; +import org.mozilla.gecko.gfx.Layer; +import org.mozilla.gecko.gfx.LayerView; +import org.mozilla.gecko.util.FloatUtils; + +public class TextSelection extends Layer { + private static final String LOGTAG = "GeckoTextSelection"; + + private final TextSelectionHandle mStartHandle; + private final TextSelectionHandle mMiddleHandle; + private final TextSelectionHandle mEndHandle; + + private float mViewLeft; + private float mViewTop; + private float mViewZoom; + + public TextSelection(TextSelectionHandle startHandle, + TextSelectionHandle middleHandle, + TextSelectionHandle endHandle) { + mStartHandle = startHandle; + mMiddleHandle = middleHandle; + mEndHandle = endHandle; + + // Only register listeners if we have valid start/middle/end handles + if (mStartHandle == null || mMiddleHandle == null || mEndHandle == null) { + Log.e(LOGTAG, "Failed to initialize text selection because at least one handle is null"); + } + } + + void destroy() { + } + + public void handleMessage(String event, JSONObject message) { + try { + if (event.equals("TextSelection:ShowHandles")) { + final JSONArray handles = message.getJSONArray("handles"); + LibreOfficeMainActivity.mAppContext.mMainHandler.post(new Runnable() { + public void run() { + try { + for (int i=0; i < handles.length(); i++) { + String handle = handles.getString(i); + + if (handle.equals("START")) + mStartHandle.setVisibility(View.VISIBLE); + else if (handle.equals("MIDDLE")) + mMiddleHandle.setVisibility(View.VISIBLE); + else + mEndHandle.setVisibility(View.VISIBLE); + } + + mViewLeft = 0.0f; + mViewTop = 0.0f; + mViewZoom = 0.0f; + LayerView layerView = LOKitShell.getLayerView(); + if (layerView != null) { + layerView.addLayer(TextSelection.this); + } + } catch(Exception e) {} + } + }); + } else if (event.equals("TextSelection:HideHandles")) { + final JSONArray handles = message.getJSONArray("handles"); + LibreOfficeMainActivity.mAppContext.mMainHandler.post(new Runnable() { + public void run() { + try { + LayerView layerView = LOKitShell.getLayerView(); + if (layerView != null) { + layerView.removeLayer(TextSelection.this); + } + + for (int i=0; i < handles.length(); i++) { + String handle = handles.getString(i); + if (handle.equals("START")) + mStartHandle.setVisibility(View.GONE); + else if (handle.equals("MIDDLE")) + mMiddleHandle.setVisibility(View.GONE); + else + mEndHandle.setVisibility(View.GONE); + } + + } catch(Exception e) {} + } + }); + } else if (event.equals("TextSelection:PositionHandles")) { + final JSONArray positions = message.getJSONArray("positions"); + LibreOfficeMainActivity.mAppContext.mMainHandler.post(new Runnable() { + public void run() { + try { + for (int i=0; i < positions.length(); i++) { + JSONObject position = positions.getJSONObject(i); + String handle = position.getString("handle"); + int left = position.getInt("left"); + int top = position.getInt("top"); + + if (handle.equals("START")) + mStartHandle.positionFromGecko(left, top); + else if (handle.equals("MIDDLE")) + mMiddleHandle.positionFromGecko(left, top); + else + mEndHandle.positionFromGecko(left, top); + } + } catch (Exception e) { } + } + }); + } + } catch (Exception e) { + Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e); + } + } + + @Override + public void draw(final RenderContext context) { + // cache the relevant values from the context and bail out if they are the same. we do this + // because this draw function gets called a lot (once per compositor frame) and we want to + // avoid doing a lot of extra work in cases where it's not needed. + 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() { + mStartHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor); + mMiddleHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor); + mEndHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor); + } + }); + } + + public void showHandle(final String handleType) { + LOKitShell.getMainHandler().post(new Runnable() { + public void run() { + try { + TextSelectionHandle handle; + if (handleType.equals("START")) + handle = mStartHandle; + else if (handleType.equals("MIDDLE")) + handle = mMiddleHandle; + else + handle = mEndHandle; + + handle.setVisibility(View.VISIBLE); + + mViewLeft = 0.0f; + mViewTop = 0.0f; + mViewZoom = 0.0f; + LayerView layerView = LOKitShell.getLayerView(); + if (layerView != null) { + layerView.addLayer(TextSelection.this); + } + } catch (Exception e) { + } + } + }); + } + + public void positionHandle(final String handleType, final RectF position) { + LOKitShell.getMainHandler().post(new Runnable() { + public void run() { + try { + TextSelectionHandle handle; + if (handleType.equals("START")) + handle = mStartHandle; + else if (handleType.equals("MIDDLE")) + handle = mMiddleHandle; + else + handle = mEndHandle; + + handle.positionFromGecko((int) position.left, (int) position.top); + } catch (Exception e) { } + } + }); + } +} diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelectionHandle.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelectionHandle.java new file mode 100644 index 000000000000..92ca9d42a114 --- /dev/null +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelectionHandle.java @@ -0,0 +1,170 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this file, +* You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import org.libreoffice.LOKitShell; +import org.libreoffice.R; +import org.mozilla.gecko.gfx.ImmutableViewportMetrics; +import org.mozilla.gecko.gfx.LayerView; + +import org.json.JSONObject; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.PointF; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +public class TextSelectionHandle extends ImageView implements View.OnTouchListener { + private static final String LOGTAG = "GeckoTextSelectionHandle"; + + private enum HandleType { START, MIDDLE, END }; + + private final HandleType mHandleType; + private final int mWidth; + private final int mHeight; + private final int mShadow; + + private int mLeft; + private int mTop; + private PointF mGeckoPoint; + private int mTouchStartX; + private int mTouchStartY; + + private RelativeLayout.LayoutParams mLayoutParams; + + public TextSelectionHandle(Context context, AttributeSet attrs) { + super(context, attrs); + setOnTouchListener(this); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextSelectionHandle); + int handleType = a.getInt(R.styleable.TextSelectionHandle_handleType, 0x01); + + if (handleType == 0x01) + mHandleType = HandleType.START; + else if (handleType == 0x02) + mHandleType = HandleType.MIDDLE; + else + mHandleType = HandleType.END; + + mGeckoPoint = new PointF(0.0f, 0.0f); + + mWidth = getResources().getDimensionPixelSize(R.dimen.text_selection_handle_width); + mHeight = getResources().getDimensionPixelSize(R.dimen.text_selection_handle_height); + mShadow = getResources().getDimensionPixelSize(R.dimen.text_selection_handle_shadow); + } + + public boolean onTouch(View v, MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: { + mTouchStartX = Math.round(event.getX()); + mTouchStartY = Math.round(event.getY()); + break; + } + case MotionEvent.ACTION_UP: { + mTouchStartX = 0; + mTouchStartY = 0; + + // Reposition handles to line up with ends of selection + JSONObject args = new JSONObject(); + try { + args.put("handleType", mHandleType.toString()); + } catch (Exception e) { + Log.e(LOGTAG, "Error building JSON arguments for TextSelection:Position"); + } + //GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("TextSelection:Position", args.toString())); + break; + } + case MotionEvent.ACTION_MOVE: { + move(Math.round(event.getX()), Math.round(event.getY())); + break; + } + } + return true; + } + + private void move(int newX, int newY) { + mLeft = mLeft + newX - mTouchStartX; + mTop = mTop + newY - mTouchStartY; + + LayerView layerView = LOKitShell.getLayerView(); + if (layerView == null) { + Log.e(LOGTAG, "Can't move selection because layerView is null"); + return; + } + // Send x coordinate on the right side of the start handle, left side of the end handle. + float left = (float) mLeft; + if (mHandleType.equals(HandleType.START)) + left += mWidth - mShadow; + else if (mHandleType.equals(HandleType.MIDDLE)) + left += (float) ((mWidth - mShadow) / 2); + else + left += mShadow; + + PointF geckoPoint = new PointF(left, (float) mTop); + geckoPoint = layerView.getLayerClient().convertViewPointToLayerPoint(geckoPoint); + + JSONObject args = new JSONObject(); + try { + args.put("handleType", mHandleType.toString()); + args.put("x", Math.round(geckoPoint.x)); + args.put("y", Math.round(geckoPoint.y)); + } catch (Exception e) { + Log.e(LOGTAG, "Error building JSON arguments for TextSelection:Move"); + } + //GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("TextSelection:Move", args.toString())); + + setLayoutPosition(); + } + + void positionFromGecko(int left, int top) { + Log.i(LOGTAG, "positionFromGecko: " + left + " " + top); + LayerView layerView = LOKitShell.getLayerView(); + if (layerView == null) { + Log.e(LOGTAG, "Can't position handle because layerView is null"); + return; + } + + mGeckoPoint = new PointF((float) left, (float) top); + ImmutableViewportMetrics metrics = layerView.getViewportMetrics(); + repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor); + } + + void repositionWithViewport(float x, float y, float zoom) { + PointF viewPoint = new PointF((mGeckoPoint.x * zoom) - x, + (mGeckoPoint.y * zoom) - y); + + mLeft = Math.round(viewPoint.x); + if (mHandleType.equals(HandleType.START)) + mLeft -= mWidth - mShadow; + else if (mHandleType.equals(HandleType.MIDDLE)) + mLeft -= (float) ((mWidth - mShadow) / 2); + else + mLeft -= mShadow; + + mTop = Math.round(viewPoint.y); + + 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); + } +} |