| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.weex.ui.component; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.support.annotation.NonNull; |
| import android.support.v4.content.LocalBroadcastManager; |
| import android.text.Layout; |
| import org.apache.weex.WXEnvironment; |
| import org.apache.weex.WXSDKInstance; |
| import org.apache.weex.annotation.Component; |
| import org.apache.weex.bridge.WXBridgeManager; |
| import org.apache.weex.common.Constants; |
| import org.apache.weex.layout.measurefunc.TextContentBoxMeasurement; |
| import org.apache.weex.ui.ComponentCreator; |
| import org.apache.weex.ui.action.BasicComponentData; |
| import org.apache.weex.ui.flat.FlatComponent; |
| import org.apache.weex.ui.flat.widget.TextWidget; |
| import org.apache.weex.ui.view.WXTextView; |
| import org.apache.weex.utils.FontDO; |
| import org.apache.weex.utils.TypefaceUtil; |
| import org.apache.weex.utils.WXLogUtils; |
| import java.lang.reflect.InvocationTargetException; |
| |
| /** |
| * Text component |
| */ |
| @Component(lazyload = false) |
| public class WXText extends WXComponent<WXTextView> implements FlatComponent<TextWidget> { |
| |
| private TextWidget mTextWidget; |
| |
| /** |
| * The default text size |
| **/ |
| public static final int sDEFAULT_SIZE = 32; |
| private BroadcastReceiver mTypefaceObserver; |
| private String mFontFamily; |
| |
| @Override |
| public boolean promoteToView(boolean checkAncestor) { |
| if (null != getInstance().getFlatUIContext()) { |
| return getInstance().getFlatUIContext().promoteToView(this, checkAncestor, WXText.class); |
| } |
| return false; |
| } |
| |
| @Override |
| @NonNull |
| public TextWidget getOrCreateFlatWidget() { |
| if (mTextWidget == null) { |
| mTextWidget = new TextWidget(getInstance().getFlatUIContext()); |
| } |
| return mTextWidget; |
| } |
| |
| @Override |
| public boolean isVirtualComponent() { |
| return !promoteToView(true); |
| } |
| |
| public static class Creator implements ComponentCreator { |
| public WXComponent createInstance(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) throws IllegalAccessException, InvocationTargetException, InstantiationException { |
| return new WXText(instance, parent, basicComponentData); |
| } |
| } |
| |
| @Deprecated |
| public WXText(WXSDKInstance instance, WXVContainer parent, String instanceId, boolean isLazy, BasicComponentData basicComponentData) { |
| this(instance, parent, basicComponentData); |
| } |
| |
| public WXText(WXSDKInstance instance, |
| WXVContainer parent, BasicComponentData basicComponentData) { |
| super(instance, parent, basicComponentData); |
| setContentBoxMeasurement(new TextContentBoxMeasurement(this)); |
| } |
| |
| @Override |
| protected WXTextView initComponentHostView(@NonNull Context context) { |
| WXTextView textView = new WXTextView(context); |
| textView.holdComponent(this); |
| return textView; |
| } |
| |
| @Override |
| public void updateExtra(Object extra) { |
| super.updateExtra(extra); |
| if(extra instanceof Layout) { |
| final Layout layout = (Layout) extra; |
| if (!promoteToView(true)) { |
| getOrCreateFlatWidget().updateTextDrawable(layout); |
| } else if (getHostView() != null && !extra.equals(getHostView().getTextLayout())) { |
| getHostView().setTextLayout(layout); |
| getHostView().invalidate(); |
| } |
| } |
| } |
| |
| @Override |
| protected void setAriaLabel(String label) { |
| WXTextView text = getHostView(); |
| if (text != null) { |
| text.setAriaLabel(label); |
| } |
| } |
| |
| @Override |
| public void refreshData(WXComponent component) { |
| super.refreshData(component); |
| if (component instanceof WXText) { |
| updateExtra(component.getExtra()); |
| } |
| } |
| |
| @Override |
| protected boolean setProperty(String key, Object param) { |
| switch (key) { |
| case Constants.Name.LINES: |
| case Constants.Name.FONT_SIZE: |
| case Constants.Name.FONT_WEIGHT: |
| case Constants.Name.FONT_STYLE: |
| case Constants.Name.COLOR: |
| case Constants.Name.TEXT_DECORATION: |
| case Constants.Name.TEXT_ALIGN: |
| case Constants.Name.TEXT_OVERFLOW: |
| case Constants.Name.LINE_HEIGHT: |
| case Constants.Name.VALUE: |
| return true; |
| case Constants.Name.FONT_FAMILY: |
| if (param != null) { |
| registerTypefaceObserver(param.toString()); |
| } |
| return true; |
| default: |
| return super.setProperty(key, param); |
| } |
| } |
| |
| @Override |
| protected Object convertEmptyProperty(String propName, Object originalValue) { |
| switch (propName) { |
| case Constants.Name.FONT_SIZE: |
| return WXText.sDEFAULT_SIZE; |
| case Constants.Name.COLOR: |
| return "black"; |
| } |
| return super.convertEmptyProperty(propName, originalValue); |
| } |
| |
| @Override |
| protected void createViewImpl() { |
| if(promoteToView(true)) { |
| super.createViewImpl(); |
| } |
| } |
| |
| @Override |
| public void destroy() { |
| super.destroy(); |
| if (WXEnvironment.getApplication() != null && mTypefaceObserver != null) { |
| WXLogUtils.d("WXText", "Unregister the typeface observer"); |
| LocalBroadcastManager.getInstance(WXEnvironment.getApplication()).unregisterReceiver(mTypefaceObserver); |
| mTypefaceObserver = null; |
| } |
| } |
| |
| private void registerTypefaceObserver(String desiredFontFamily) { |
| if (WXEnvironment.getApplication() == null) { |
| WXLogUtils.w("WXText", "ApplicationContent is null on register typeface observer"); |
| return; |
| } |
| mFontFamily = desiredFontFamily; |
| if (mTypefaceObserver != null) { |
| return; |
| } |
| |
| mTypefaceObserver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String fontFamily = intent.getStringExtra("fontFamily"); |
| if (!mFontFamily.equals(fontFamily)) { |
| return; |
| } |
| |
| FontDO fontDO = TypefaceUtil.getFontDO(fontFamily); |
| if (fontDO != null && fontDO.getTypeface() != null && getHostView() != null) { |
| WXTextView hostView = getHostView(); |
| Layout layout = hostView.getTextLayout(); |
| if (layout != null) { |
| layout.getPaint().setTypeface(fontDO.getTypeface()); |
| } else { |
| WXLogUtils.d("WXText", "Layout not created"); |
| } |
| WXBridgeManager |
| .getInstance().markDirty(getInstanceId(), getRef(), true); |
| forceRelayout(); |
| |
| } |
| } |
| }; |
| |
| LocalBroadcastManager.getInstance(WXEnvironment.getApplication()).registerReceiver(mTypefaceObserver, new IntentFilter(TypefaceUtil.ACTION_TYPE_FACE_AVAILABLE)); |
| } |
| |
| |
| @Override |
| protected void layoutDirectionDidChanged(boolean isRTL) { |
| forceRelayout(); |
| } |
| |
| private void forceRelayout(){ |
| WXBridgeManager.getInstance().post(new Runnable() { |
| @Override |
| public void run() { |
| if(contentBoxMeasurement instanceof TextContentBoxMeasurement){ |
| ((TextContentBoxMeasurement) contentBoxMeasurement).forceRelayout(); |
| } |
| } |
| }); |
| } |
| } |