Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dom): measure textinput node #3361

Merged
merged 2 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ constexpr char kHeight[] = "height";
constexpr char kLeft[] = "left";
constexpr char kTop[] = "top";
constexpr char kProps[] = "props";
constexpr char kMeasureNode[] = "Text";
constexpr char kDeleteProps[] = "deleteProps";
constexpr char kFontStyle[] = "fontStyle";
constexpr char kLetterSpacing[] = "letterSpacing";
Expand Down Expand Up @@ -73,6 +72,10 @@ namespace hippy {
inline namespace render {
inline namespace native {

static bool IsMeasureNode(const std::string &name) {
return name == "Text" || name == "TextInput";
}

std::atomic<uint32_t> NativeRenderManager::unique_native_render_manager_id_{1};
footstone::utils::PersistentObjectMap<uint32_t, std::shared_ptr<hippy::NativeRenderManager>> NativeRenderManager::persistent_map_;

Expand Down Expand Up @@ -112,7 +115,7 @@ void NativeRenderManager::CreateRenderNode(std::weak_ptr<RootNode> root_node,
dom_node[kIndex] = footstone::value::HippyValue(render_info.index);
dom_node[kName] = footstone::value::HippyValue(nodes[i]->GetViewName());

if (nodes[i]->GetViewName() == kMeasureNode) {
if (IsMeasureNode(nodes[i]->GetViewName())) {
int32_t id = footstone::check::checked_numeric_cast<uint32_t, int32_t>(nodes[i]->GetId());
MeasureFunction measure_function = [WEAK_THIS, root_id, id](float width, LayoutMeasureMode width_measure_mode,
float height, LayoutMeasureMode height_measure_mode,
Expand Down Expand Up @@ -329,7 +332,7 @@ void NativeRenderManager::UpdateLayout(std::weak_ptr<RootNode> root_node,
dom_node[kHeight] = footstone::value::HippyValue(DpToPx(result.height));
dom_node[kLeft] = footstone::value::HippyValue(DpToPx(result.left));
dom_node[kTop] = footstone::value::HippyValue(DpToPx(result.top));
if (nodes[i]->GetViewName() == kMeasureNode) {
if (IsMeasureNode(nodes[i]->GetViewName())) {
dom_node["paddingLeft"] = footstone::value::HippyValue(DpToPx(result.paddingLeft));
dom_node["paddingTop"] = footstone::value::HippyValue(DpToPx(result.paddingTop));
dom_node["paddingRight"] = footstone::value::HippyValue(DpToPx(result.paddingRight));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ public class NodeProps {
public static final String VIEW_CLASS_NAME = "View";
public static final String TEXT_CLASS_NAME = "Text";
public static final String IMAGE_CLASS_NAME = "Image";
public static final String TEXT_INPUT_CLASS_NAME = "TextInput";
public static final String IMAGE_SPAN_TEXT = "[img]";

public static final String STYLE = "style";
public static final String PROPS = "props";
public static final String ROOT_NODE = "RootNode";
public static final String CUSTOM_PROP = "customProp";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ void findViewPropsMethod(Class<?> cls,
private void invokePropMethod(@NonNull Object obj, @NonNull Object arg1,
Map<String, Object> props, String key, @NonNull PropertyMethodHolder methodHolder) {
try {
if (props.get(key) == null) {
Object value = props.get(key);
if (value == null) {
switch (methodHolder.defaultType) {
case HippyControllerProps.BOOLEAN:
methodHolder.method.invoke(obj, arg1, methodHolder.defaultBoolean);
Expand All @@ -147,7 +148,6 @@ private void invokePropMethod(@NonNull Object obj, @NonNull Object arg1,
break;
}
} else {
Object value = props.get(key);
if (methodHolder.paramTypes == null) {
methodHolder.paramTypes = methodHolder.method.getGenericParameterTypes();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -737,8 +737,9 @@ public void exec() {
public long measure(int rootId, int nodeId, float width, int widthMode, float height,
int heightMode) {
try {
FlexMeasureMode flexMeasureMode = FlexMeasureMode.fromInt(widthMode);
return mVirtualNodeManager.measure(rootId, nodeId, width, flexMeasureMode);
FlexMeasureMode wm = FlexMeasureMode.fromInt(widthMode);
FlexMeasureMode hm = FlexMeasureMode.fromInt(heightMode);
return mVirtualNodeManager.measure(rootId, nodeId, width, wm, height, hm);
} catch (NativeRenderException e) {
handleRenderException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ protected TextImageSpan createImageSpan() {
if (mDefaultSource != null && imageLoader != null) {
ImageDataSupplier supplier = imageLoader.fetchImageSync(mDefaultSource, null, mWidth,
mHeight);
Bitmap bitmap = supplier.getBitmap();
if (bitmap != null) {
Resources resources = ContextHolder.getAppContext().getResources();
drawable = new BitmapDrawable(resources, bitmap);
if (supplier != null) {
Bitmap bitmap = supplier.getBitmap();
if (bitmap != null) {
Resources resources = ContextHolder.getAppContext().getResources();
drawable = new BitmapDrawable(resources, bitmap);
}
}
}
if (drawable == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* Tencent is pleased to support the open source community by making Hippy available.
* Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.tencent.renderer.node;

import android.text.SpannableStringBuilder;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import androidx.annotation.NonNull;
import com.tencent.mtt.hippy.annotation.HippyControllerProps;
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.utils.ContextHolder;
import com.tencent.mtt.hippy.utils.PixelUtil;
import com.tencent.renderer.utils.FlexUtils;
import com.tencent.renderer.utils.FlexUtils.FlexMeasureMode;
import java.util.List;

public class TextInputVirtualNode extends VirtualNode {

protected long mMeasureSize = 0;
protected int mNumberOfLines = 0;
protected int mFontSize = (int) Math.ceil(PixelUtil.dp2px(NodeProps.FONT_SIZE_SP));
@NonNull
private final EditText mEditText;

public TextInputVirtualNode(int rootId, int id, int pid, int index) {
super(rootId, id, pid, index);
mEditText = new EditText(ContextHolder.getAppContext());
mEditText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
}

protected void createSpanOperation(List<SpanOperation> ops,
SpannableStringBuilder builder, boolean useChild) {
// Need do nothing by default
}

@SuppressWarnings("unused")
@HippyControllerProps(name = NodeProps.NUMBER_OF_LINES, defaultType = HippyControllerProps.NUMBER)
public void setNumberOfLines(int numberOfLines) {
mNumberOfLines = numberOfLines;
}

@SuppressWarnings("unused")
@HippyControllerProps(name = NodeProps.FONT_SIZE, defaultType = HippyControllerProps.NUMBER,
defaultNumber = NodeProps.FONT_SIZE_SP)
public void setFontSize(float size) {
mFontSize = (int) Math.ceil(PixelUtil.dp2px(size));
}

private int getMeasureSpec(float size, FlexMeasureMode mode) {
switch (mode) {
case EXACTLY:
return View.MeasureSpec.makeMeasureSpec((int) size, View.MeasureSpec.EXACTLY);
case AT_MOST:
return View.MeasureSpec.makeMeasureSpec((int) size, View.MeasureSpec.AT_MOST);
default:
return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
}
}

public long measure(float width, FlexMeasureMode widthMode, float height, FlexMeasureMode heightMode) {
mEditText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mFontSize);
if (mNumberOfLines > 0) {
mEditText.setLines(mNumberOfLines);
}
mEditText.measure(getMeasureSpec(width, widthMode), getMeasureSpec(height, heightMode));
return FlexUtils.makeSizeToLong(mEditText.getMeasuredWidth(), mEditText.getMeasuredHeight());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static com.tencent.mtt.hippy.dom.node.NodeProps.PADDING_RIGHT;
import static com.tencent.mtt.hippy.dom.node.NodeProps.PADDING_TOP;
import static com.tencent.mtt.hippy.dom.node.NodeProps.TEXT_CLASS_NAME;
import static com.tencent.mtt.hippy.dom.node.NodeProps.TEXT_INPUT_CLASS_NAME;
import static com.tencent.renderer.NativeRenderException.ExceptionCode.INVALID_MEASURE_STATE_ERR;
import static com.tencent.renderer.NativeRenderer.NODE_ID;
import static com.tencent.renderer.NativeRenderer.NODE_INDEX;
Expand All @@ -32,7 +33,6 @@
import androidx.annotation.Nullable;

import com.tencent.mtt.hippy.annotation.HippyControllerProps;
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.utils.LogUtils;
import com.tencent.renderer.NativeRender;
import com.tencent.renderer.NativeRenderException;
Expand Down Expand Up @@ -101,7 +101,7 @@ public VirtualNode checkVirtualParent(int rootId, int nodeId) {
*/
public boolean updateEventListener(int rootId, int nodeId, @NonNull Map<String, Object> props) {
VirtualNode node = getVirtualNode(rootId, nodeId);
if (node == null) {
if (node == null || node instanceof TextInputVirtualNode) {
return false;
}
boolean isChanged = false;
Expand Down Expand Up @@ -169,9 +169,13 @@ public TextRenderSupplier updateLayout(int rootId, int nodeId, float width,
rightPadding, bottomPadding);
}

public long measure(int rootId, int nodeId, float width, FlexMeasureMode widthMode)
public long measure(int rootId, int nodeId, float width, FlexMeasureMode widthMode,
float height, FlexMeasureMode heightMode)
throws NativeRenderException {
VirtualNode node = getVirtualNode(rootId, nodeId);
if (node instanceof TextInputVirtualNode) {
return ((TextInputVirtualNode) node).measure(width, widthMode, height, heightMode);
}
if (!(node instanceof TextVirtualNode) || node.mParent != null) {
throw new NativeRenderException(INVALID_MEASURE_STATE_ERR,
TAG + ": measure: encounter wrong state when check node, "
Expand Down Expand Up @@ -215,15 +219,10 @@ private void findPropertyMethod(Class nodeClass,

@SuppressWarnings("rawtypes")
private void invokePropertyMethod(@NonNull VirtualNode node, @NonNull Map props,
@NonNull String key, @Nullable PropertyMethodHolder methodHolder) {
if (methodHolder == null) {
if (key.equals(NodeProps.STYLE) && (props.get(key) instanceof Map)) {
updateProps(node, (Map) props.get(key));
}
return;
}
@NonNull String key, @NonNull PropertyMethodHolder methodHolder) {
try {
if (props.get(key) == null) {
Object value = props.get(key);
if (value == null) {
switch (methodHolder.defaultType) {
case HippyControllerProps.BOOLEAN:
methodHolder.method.invoke(node, methodHolder.defaultBoolean);
Expand All @@ -248,7 +247,7 @@ private void invokePropertyMethod(@NonNull VirtualNode node, @NonNull Map props,
}
} else {
methodHolder.method.invoke(node,
PropertyUtils.convertProperty(methodHolder.paramTypes[0], props.get(key)));
PropertyUtils.convertProperty(methodHolder.paramTypes[0], value));
}
} catch (Exception exception) {
mNativeRenderer.handleRenderException(
Expand All @@ -271,7 +270,9 @@ private void updateProps(@NonNull VirtualNode node, @Nullable Map<String, Object
Set<String> keySet = props.keySet();
for (String key : keySet) {
PropertyMethodHolder methodHolder = methodMap.get(key);
invokePropertyMethod(node, props, key, methodHolder);
if (methodHolder != null) {
invokePropertyMethod(node, props, key, methodHolder);
}
}
}

Expand All @@ -281,7 +282,7 @@ private VirtualNode createVirtualNode(int rootId, int id, int pid, int index,
VirtualNode node = mNativeRenderer.createVirtualNode(rootId, id, pid, index, className,
props);
VirtualNode parent = getVirtualNode(rootId, pid);
// Only text or text child need to create virtual node.
// Only text、text child and text input need to create virtual node.
if (className.equals(TEXT_CLASS_NAME)) {
if (!(node instanceof TextVirtualNode)) {
node = new TextVirtualNode(rootId, id, pid, index, mNativeRenderer);
Expand All @@ -290,6 +291,10 @@ private VirtualNode createVirtualNode(int rootId, int id, int pid, int index,
if (!(node instanceof ImageVirtualNode)) {
node = new ImageVirtualNode(rootId, id, pid, index, mNativeRenderer);
}
} else if (className.equals(TEXT_INPUT_CLASS_NAME)) {
if (!(node instanceof TextInputVirtualNode)) {
node = new TextInputVirtualNode(rootId, id, pid, index);
}
}
return node;
}
Expand Down Expand Up @@ -331,6 +336,11 @@ public void updateNode(int rootId, int id, @Nullable Map<String, Object> diffPro
}
}
updateProps(node, propsToUpdate);
// The text input node is only used for measurement purposes and does not
// require any layout updates
if (node instanceof TextInputVirtualNode) {
return;
}
// add the top VirtualNode to mUpdateNodes
while (node.mParent != null) {
node = node.mParent;
Expand Down Expand Up @@ -374,7 +384,7 @@ public void moveNode(int rootId, @NonNull VirtualNode parent, @NonNull List<Obje
for (int i = 0; i < list.size(); i++) {
try {
final Map node = (Map) list.get(i);
Integer nodeId = ((Number) Objects.requireNonNull(node.get(NODE_ID))).intValue();
int nodeId = ((Number) Objects.requireNonNull(node.get(NODE_ID))).intValue();
int index = ((Number) Objects.requireNonNull(node.get(NODE_INDEX))).intValue();
VirtualNode child = getVirtualNode(rootId, nodeId);
if (child != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.tencent.mtt.hippy.dom.node.NodeProps;

import com.tencent.mtt.hippy.uimanager.ControllerManager;
import com.tencent.renderer.node.RenderNode;
import com.tencent.mtt.hippy.utils.LogUtils;
Expand All @@ -37,29 +35,6 @@ public class DiffUtils {
private static final String TINT_COLORS = "tintColors";
private static final String TINT_COLOR = "tintColor";

@SuppressWarnings({"unchecked", "rawtypes"})
@Nullable
private static Map<String, Object> findResetStyles(@Nullable Map<String, Object> fromProps,
@Nullable Map<String, Object> toProps) {
Map<String, Object> diffStyles = null;
Map<String, Object> fromStyle =
(fromProps != null) ? (Map) fromProps.get(NodeProps.STYLE) : null;
if (fromStyle == null) {
return null;
}
Map<String, Object> toStyle = (toProps != null) ? (Map) toProps.get(NodeProps.STYLE) : null;
Set<String> styleKeys = fromStyle.keySet();
for (String styleKey : styleKeys) {
if (toStyle == null || !toStyle.containsKey(styleKey)) {
if (diffStyles == null) {
diffStyles = new HashMap<>();
}
diffStyles.put(styleKey, null);
}
}
return diffStyles;
}

/**
* Find the attribute that exists in the from node but does not exist in the to node.
*
Expand All @@ -79,18 +54,9 @@ public static Map<String, Object> findResetProps(@Nullable Map<String, Object> f
return null;
}
Map<String, Object> diffProps = null;
Map<String, Object> diffStyles;
Set<String> fromKeys = fromProps.keySet();
try {
diffStyles = findResetStyles(fromProps, toProps);
if (diffStyles != null) {
diffProps = new HashMap<>();
diffProps.put(NodeProps.STYLE, diffStyles);
}
for (String fromKey : fromKeys) {
if (fromKey.equals(NodeProps.STYLE)) {
continue;
}
if (toProps == null || !toProps.containsKey(fromKey)) {
if (diffProps == null) {
diffProps = new HashMap<>();
Expand Down Expand Up @@ -162,9 +128,6 @@ private static void diffProperty(@NonNull String fromKey, @Nullable Object fromV
if (diffResult.isEmpty()) {
return;
}
} else if (diffLevel == 0 && fromKey.equals(NodeProps.STYLE)) {
diffResult = diffMap((Map) fromValue, new HashMap<String, Object>(),
diffLevel + 1, controllerManager, componentProps);
}
updateProps.put(fromKey, diffResult);
}
Expand Down