Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
CursorHandle.java
Go to the documentation of this file.
1// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4package org.qtproject.qt.android;
5
6import android.content.Context;
7import android.os.Bundle;
8import android.util.DisplayMetrics;
9import android.view.LayoutInflater;
10import android.view.View;
11import android.widget.LinearLayout;
12import android.widget.ImageView;
13import android.content.res.TypedArray;
14import android.graphics.drawable.Drawable;
15import android.view.MotionEvent;
16import android.widget.PopupWindow;
17import android.app.Activity;
18import android.util.TypedValue;
19import android.view.ViewTreeObserver;
20
21/* This view represents one of the handle (selection or cursor handle) */
22class CursorView extends ImageView
23{
24 private CursorHandle mHandle;
25 // The coordinare which where clicked
26 private float m_offsetX;
27 private float m_offsetY;
28 private boolean m_pressed = false;
29
30 CursorView (Context context, CursorHandle handle) {
31 super(context);
32 mHandle = handle;
33 }
34
35 // Called when the handle was moved programmatically , with the delta amount in pixels
36 public void adjusted(int dx, int dy) {
37 m_offsetX += dx;
38 m_offsetY += dy;
39 }
40
41 @Override
42 public boolean onTouchEvent(MotionEvent ev) {
43 switch (ev.getActionMasked()) {
44 case MotionEvent.ACTION_DOWN: {
45 m_offsetX = ev.getRawX();
46 m_offsetY = ev.getRawY() + getHeight() / 2;
47 m_pressed = true;
48 break;
49 }
50
51 case MotionEvent.ACTION_MOVE: {
52 if (!m_pressed)
53 return false;
54 mHandle.updatePosition(Math.round(ev.getRawX() - m_offsetX),
55 Math.round(ev.getRawY() - m_offsetY));
56 break;
57 }
58
59 case MotionEvent.ACTION_UP:
60 case MotionEvent.ACTION_CANCEL:
61 m_pressed = false;
62 break;
63 }
64 return true;
65 }
66
67}
68
69// Helper class that manages a cursor or selection handle
70public class CursorHandle implements ViewTreeObserver.OnPreDrawListener
71{
72 private View m_layout = null;
73 private CursorView m_cursorView = null;
74 private PopupWindow m_popup = null;
75 private int m_id;
76 private int m_attr;
77 private Activity m_activity;
78 private int m_posX = 0;
79 private int m_posY = 0;
80 private int m_lastX;
81 private int m_lastY;
82 int tolerance;
83 private boolean m_rtl;
84 int m_yShift;
85
86 public CursorHandle(Activity activity, View layout, int id, int attr, boolean rtl) {
87 m_activity = activity;
88 m_id = id;
89 m_attr = attr;
90 m_layout = layout;
91 DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
92 m_yShift = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1f, metrics);
93 tolerance = Math.min(1, (int)(m_yShift / 2f));
94 m_lastX = m_lastY = -1 - tolerance;
95 m_rtl = rtl;
96 }
97
98 private boolean initOverlay(){
99 if (m_popup == null){
100
101 Context context = m_layout.getContext();
102 int[] attrs = {m_attr};
103 TypedArray a = context.getTheme().obtainStyledAttributes(attrs);
104 Drawable drawable = a.getDrawable(0);
105
106 m_cursorView = new CursorView(context, this);
107 m_cursorView.setImageDrawable(drawable);
108
109 m_popup = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle);
110 m_popup.setSplitTouchEnabled(true);
111 m_popup.setClippingEnabled(false);
112 m_popup.setContentView(m_cursorView);
113 m_popup.setWidth(drawable.getIntrinsicWidth());
114 m_popup.setHeight(drawable.getIntrinsicHeight());
115
116 m_layout.getViewTreeObserver().addOnPreDrawListener(this);
117 }
118 return true;
119 }
120
121 // Show the handle at a given position (or move it if it is already shown)
122 public void setPosition(final int x, final int y){
123 initOverlay();
124
125 final int[] layoutLocation = new int[2];
126 m_layout.getLocationOnScreen(layoutLocation);
127
128 // These values are used for handling split screen case
129 final int[] activityLocation = new int[2];
130 final int[] activityLocationInWindow = new int[2];
131 m_activity.getWindow().getDecorView().getLocationOnScreen(activityLocation);
132 m_activity.getWindow().getDecorView().getLocationInWindow(activityLocationInWindow);
133
134 int x2 = x + layoutLocation[0] - activityLocation[0];
135 int y2 = y + layoutLocation[1] + m_yShift + (activityLocationInWindow[1] - activityLocation[1]);
136
137 if (m_id == QtNative.IdCursorHandle) {
138 x2 -= m_popup.getWidth() / 2 ;
139 } else if ((m_id == QtNative.IdLeftHandle && !m_rtl) || (m_id == QtNative.IdRightHandle && m_rtl)) {
140 x2 -= m_popup.getWidth() * 3 / 4;
141 } else {
142 x2 -= m_popup.getWidth() / 4;
143 }
144
145 if (m_popup.isShowing()) {
146 m_popup.update(x2, y2, -1, -1);
147 m_cursorView.adjusted(x - m_posX, y - m_posY);
148 } else {
149 m_popup.showAtLocation(m_layout, 0, x2, y2);
150 }
151
152 m_posX = x;
153 m_posY = y;
154 }
155
156 public int bottom()
157 {
158 initOverlay();
159 final int[] location = new int[2];
160 m_cursorView.getLocationOnScreen(location);
161 return location[1] + m_cursorView.getHeight();
162 }
163
164 public void hide() {
165 if (m_popup != null) {
166 m_popup.dismiss();
167 }
168 }
169
170 public int width()
171 {
172 return m_cursorView.getDrawable().getIntrinsicWidth();
173 }
174
175 // The handle was dragged by a given relative position
176 public void updatePosition(int x, int y) {
177 y -= m_yShift;
178 if (Math.abs(m_lastX - x) > tolerance || Math.abs(m_lastY - y) > tolerance) {
179 QtNative.handleLocationChanged(m_id, x + m_posX, y + m_posY);
180 m_lastX = x;
181 m_lastY = y;
182 }
183 }
184
185 @Override
186 public boolean onPreDraw() {
187 // This hook is called when the view location is changed
188 // For example if the keyboard appears.
189 // Adjust the position of the handle accordingly
190 if (m_popup != null && m_popup.isShowing())
191 setPosition(m_posX, m_posY);
192
193 return true;
194 }
195}
void setPosition(final int x, final int y)
CursorHandle(Activity activity, View layout, int id, int attr, boolean rtl)
static native void handleLocationChanged(int id, int x, int y)
static void * context
static struct AttrInfo attrs[]
n void setPosition(void) \n\
GLint location
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint id
[7]
GLfloat GLfloat f
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLint y
GLfixed GLfixed GLfixed y2
GLfixed GLfixed x2
XID Drawable
QVBoxLayout * layout