Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
EditPopupMenu.java
Go to the documentation of this file.
1// Copyright (C) 2018 BogDan Vatra <bogdan@kde.org>
2// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5package org.qtproject.qt.android;
6
7import android.app.Activity;
8import android.graphics.Point;
9import android.util.Log;
10import android.view.View;
11import android.view.ViewGroup;
12import android.view.ViewTreeObserver;
13import android.widget.PopupWindow;
14
15// Helper class that manages a cursor or selection handle
16class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, View.OnLayoutChangeListener,
17 View.OnAttachStateChangeListener, EditContextView.OnClickListener
18{
19 private final EditContextView m_view;
20 private final QtEditText m_editText;
21
22 private PopupWindow m_popup = null;
23 private final Activity m_activity;
24 private int m_posX;
25 private int m_posY;
26 private int m_buttons;
27 private ViewTreeObserver m_observer;
28
29 EditPopupMenu(QtEditText editText)
30 {
31 m_activity = (Activity) editText.getContext();
32 m_view = new EditContextView(m_activity, this);
33 m_view.addOnLayoutChangeListener(this);
34
35 m_editText = editText;
36 m_editText.addOnAttachStateChangeListener(this);
37 }
38
40 public void onViewAttachedToWindow(View view)
41 {
42 m_observer = view.getViewTreeObserver();
43 m_observer.addOnPreDrawListener(this);
44 }
45
47 public void onViewDetachedFromWindow(View view)
48 {
49 // The activity observer outlives the edit control and its QtWindow.
50 if (m_observer != null && m_observer.isAlive())
51 m_observer.removeOnPreDrawListener(this);
52 m_observer = null;
53 hide();
54 }
55
56 private void initOverlay()
57 {
58 if (m_popup != null)
59 return;
60
61 m_popup = new PopupWindow(m_activity, null, android.R.attr.textSelectHandleWindowStyle);
62 m_popup.setSplitTouchEnabled(true);
63 m_popup.setClippingEnabled(false);
64 m_popup.setContentView(m_view);
65 m_popup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
66 m_popup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
67 }
68
69 // Show the handle at a given position (or move it if it is already shown)
70 void setPosition(final int x, final int y, final int buttons)
71 {
72 initOverlay();
73
74 m_view.updateButtons(buttons);
75 Point viewSize = m_view.getCalculatedSize();
76
77 final int[] layoutLocation = new int[2];
78
79 // Since QtEditText doesn't match the QtWindow size, we should use its parent for
80 // EditPopupMenu positioning. However, there may be cases where the parent is
81 // not set. In such cases, we need to use QtEditText instead.
82 View positioningView = (View) m_editText.getParent();
83 if (positioningView == null)
84 positioningView = m_editText;
85 positioningView.getLocationOnScreen(layoutLocation);
86
87 // These values are used for handling split screen case
88 final int[] activityLocation = new int[2];
89 final int[] activityLocationInWindow = new int[2];
90 m_activity.getWindow().getDecorView().getLocationOnScreen(activityLocation);
91 m_activity.getWindow().getDecorView().getLocationInWindow(activityLocationInWindow);
92
93 int x2 = x + layoutLocation[0] - activityLocation[0];
94 int y2 = y + layoutLocation[1] + (activityLocationInWindow[1] - activityLocation[1]);
95
96 x2 -= viewSize.x / 2 ;
97
98 y2 -= viewSize.y;
99 if (y2 < 0)
100 y2 = m_editText.getSelectionHandleBottom();
101
102 if (y2 <= 0) {
103 try {
104 QtLayout parentLayout = (QtLayout) m_editText.getParent();
105 parentLayout.requestLayout();
106 } catch (ClassCastException e) {
107 Log.w(QtNative.QtTAG, "QtEditText " + m_editText + " parent is not a QtLayout, " +
108 "requestLayout() skipped");
109 } catch (NullPointerException e) {
110 Log.w(QtNative.QtTAG, "QtEditText " + m_editText + " does not have a parent, " +
111 "requestLayout() skipped");
112 }
113 }
114
115 if (positioningView.getWidth() < x + viewSize.x / 2)
116 x2 = positioningView.getWidth() - viewSize.x;
117
118 if (x2 < 0)
119 x2 = 0;
120
121 if (m_popup.isShowing())
122 m_popup.update(x2, y2, -1, -1);
123 else
124 m_popup.showAtLocation(positioningView, 0, x2, y2);
125
126 m_posX = x;
127 m_posY = y;
128 m_buttons = buttons;
129 }
130
131 void hide() {
132 if (m_popup != null) {
133 m_popup.dismiss();
134 m_popup = null;
135 }
136 }
137
138 @Override
139 public boolean onPreDraw() {
140 // This hook is called when the view location is changed
141 // For example if the keyboard appears.
142 // Adjust the position of the handle accordingly
143 if (m_popup != null && m_popup.isShowing())
144 setPosition(m_posX, m_posY, m_buttons);
145
146 return true;
147 }
148
149 @Override
150 public void onLayoutChange(View v, int left, int top, int right, int bottom,
151 int oldLeft, int oldTop, int oldRight, int oldBottom)
152 {
153 if ((right - left != oldRight - oldLeft || bottom - top != oldBottom - oldTop) &&
154 m_popup != null && m_popup.isShowing())
155 setPosition(m_posX, m_posY, m_buttons);
156 }
157
158 @Override
159 public void contextButtonClicked(int buttonId) {
160 switch (buttonId) {
161 case android.R.string.cut:
162 QtInputConnection.QtNativeInputConnection.cut();
163 break;
164 case android.R.string.copy:
165 QtInputConnection.QtNativeInputConnection.copy();
166 break;
167 case android.R.string.paste:
168 QtInputConnection.QtNativeInputConnection.paste();
169 break;
170 case android.R.string.selectAll:
171 QtInputConnection.QtNativeInputConnection.selectAll();
172 break;
173 }
174 hide();
175 }
176}
GLdouble GLdouble right
GLint GLint GLint GLint GLint x
GLint GLint bottom
GLdouble GLdouble GLdouble GLdouble top
GLsizei const GLfloat * v
GLint y
GLint left
GLfixed GLfixed GLfixed y2
GLfixed GLfixed x2
QQuickView * view
[0]