summaryrefslogtreecommitdiff
path: root/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/TextSelection.java
blob: 52aa5554fb4bdb7f2afc19835848491c92d6941f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* 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.app.Activity;
import android.graphics.RectF;
import android.util.Log;
import android.view.View;

import org.libreoffice.LOKitShell;
import org.libreoffice.R;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.util.FloatUtils;

import static org.mozilla.gecko.TextSelectionHandle.HandleType.MIDDLE;
import static org.mozilla.gecko.TextSelectionHandle.HandleType.START;

/**
 * TextSelection operates the text selection (start, middle and end) handles. It is a Layer implementation
 * that intercepts viewport changes and repositions the text handles accordingly.
 */
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(Activity context) {
        mStartHandle = (TextSelectionHandle) context.findViewById(R.id.start_handle);
        mMiddleHandle = (TextSelectionHandle) context.findViewById(R.id.middle_handle);
        mEndHandle = (TextSelectionHandle) context.findViewById(R.id.end_handle);

        // 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");
        }
    }

    /**
     * Destroys created resources if any were created.
     */
    void destroy() {
    }

    /**
     * Reposition the handles when draw happens.
     */
    @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);
            }
        });
    }

    /**
     * Shows the requested handle.
     */
    public void showHandle(final TextSelectionHandle.HandleType handleType) {
        LOKitShell.getMainHandler().post(new Runnable() {
            public void run() {
                TextSelectionHandle handle = getHandle(handleType);

                handle.setVisibility(View.VISIBLE);

                mViewLeft = 0.0f;
                mViewTop = 0.0f;
                mViewZoom = 0.0f;
                LayerView layerView = LOKitShell.getLayerView();
                if (layerView != null) {
                    layerView.addLayer(TextSelection.this);
                }
            }
        });
    }

    /**
     * Get instance of the requested handle type..
     */
    private TextSelectionHandle getHandle(TextSelectionHandle.HandleType handleType) {
        if (handleType == START) {
            return mStartHandle;
        } else if (handleType == MIDDLE) {
            return mMiddleHandle;
        } else {
            return mEndHandle;
        }
    }

    /**
     * Hides the requested handle.
     */
    public void hideHandle(final TextSelectionHandle.HandleType handleType) {
        LOKitShell.getMainHandler().post(new Runnable() {
            public void run() {
                TextSelectionHandle handle = getHandle(handleType);
                handle.setVisibility(View.GONE);
            }
        });
    }

    /**
     * Position the handle requested handle to the input rectangle (expressed in document coordinates)
     */
    public void positionHandle(final TextSelectionHandle.HandleType handleType, final RectF position) {
        LOKitShell.getMainHandler().post(new Runnable() {
            public void run() {
                TextSelectionHandle handle = getHandle(handleType);
                handle.positionFromGecko(position, false);
            }
        });
    }
}