private static String mapIntToStringUsingAnnotation( int value, @Nullable ViewDebug.ExportedProperty annotation) { if (!canIntBeMappedToString(annotation)) { throw new IllegalStateException("Cannot map using this annotation"); } for (ViewDebug.IntToString map : annotation.mapping()) { if (map.from() == value) { return map.to(); } } // no mapping was found even though one was expected ): return NONE_MAPPING; }
private void getStyleFromValue( View element, String name, Object value, @Nullable ViewDebug.ExportedProperty annotation, StyleAccumulator styles) { if (name.equals(ID_NAME)) { getIdStyle(element, styles); } else if (value instanceof Integer) { getStyleFromInteger(name, (Integer) value, annotation, styles); } else if (value instanceof Float) { getStyleFromFloat(name, (Float) value, annotation, styles); } else { getStylesFromObject(element, name, value, annotation, styles); } }
private void getStyleFromInteger( String name, Integer value, @Nullable ViewDebug.ExportedProperty annotation, StyleAccumulator styles) { String intValueStr = IntegerFormatter.getInstance().format(value, annotation); if (canIntBeMappedToString(annotation)) { styles.store( name, intValueStr + " (" + mapIntToStringUsingAnnotation(value, annotation) + ")", false); } else if (canFlagsBeMappedToString(annotation)) { styles.store( name, intValueStr + " (" + mapFlagsToStringUsingAnnotation(value, annotation) + ")", false); } else { styles.store(name, intValueStr, isDefaultValue(value, annotation)); } }
private static String mapFlagsToStringUsingAnnotation( int value, @Nullable ViewDebug.ExportedProperty annotation) { if (!canFlagsBeMappedToString(annotation)) { throw new IllegalStateException("Cannot map using this annotation"); } StringBuilder stringBuilder = null; boolean atLeastOneFlag = false; for (ViewDebug.FlagToString flagToString : annotation.flagMapping()) { if (flagToString.outputIf() == ((value & flagToString.mask()) == flagToString.equals())) { if (stringBuilder == null) { stringBuilder = new StringBuilder(); } if (atLeastOneFlag) { stringBuilder.append(" | "); } stringBuilder.append(flagToString.name()); atLeastOneFlag = true; } } if (atLeastOneFlag) { return stringBuilder.toString(); } else { return NONE_MAPPING; } }
private void getStyleFromValue( View element, String name, Object value, @Nullable ViewDebug.ExportedProperty annotation, StyleAccumulator styles) { if (name.equals(ID_NAME)) { getIdStyle(element, styles); } else if (value instanceof Integer) { getStyleFromInteger(name, (Integer) value, annotation, styles); } else if (value instanceof Float) { styles.store(name, String.valueOf(value), ((Float) value) == 0.0f); } else if (value instanceof Boolean) { styles.store(name, String.valueOf(value), false); } else if (value instanceof Short) { styles.store(name, String.valueOf(value), ((Short) value) == 0); } else if (value instanceof Long) { styles.store(name, String.valueOf(value), ((Long) value) == 0); } else if (value instanceof Double) { styles.store(name, String.valueOf(value), ((Double) value) == 0.0d); } else if (value instanceof Byte) { styles.store(name, String.valueOf(value), ((Byte) value) == 0); } else if (value instanceof Character) { styles.store(name, String.valueOf(value), ((Character) value) == Character.MIN_VALUE); } else if (value instanceof CharSequence) { styles.store(name, String.valueOf(value), ((CharSequence) value).length() == 0); } else { getStylesFromObject(element, name, value, annotation, styles); } }
private void getStyleFromInteger( String name, Integer value, @Nullable ViewDebug.ExportedProperty annotation, StyleAccumulator styles) { String intValueStr = IntegerFormatter.getInstance().format(value, annotation); if (canIntBeMappedToString(annotation)) { styles.store( name, intValueStr + " (" + mapIntToStringUsingAnnotation(value, annotation) + ")", false); } else if (canFlagsBeMappedToString(annotation)) { styles.store( name, intValueStr + " (" + mapFlagsToStringUsingAnnotation(value, annotation) + ")", false); } else { Boolean defaultValue = true; // Mappable ints should always be shown, because enums don't necessarily have // logical "default" values. Thus we mark all of them as not default, so that they // show up in the inspector. if (value != 0 || canFlagsBeMappedToString(annotation) || canIntBeMappedToString(annotation)) { defaultValue = false; } styles.store(name, intValueStr, defaultValue); } }
public FieldBackedCSSProperty( Field field, String cssName, @Nullable ViewDebug.ExportedProperty annotation) { super(cssName, annotation); mField = field; mField.setAccessible(true); }
public MethodBackedCSSProperty( Method method, String cssName, @Nullable ViewDebug.ExportedProperty annotation) { super(cssName, annotation); mMethod = method; mMethod.setAccessible(true); }
@Override @ViewDebug.ExportedProperty public View getSelectedView() { if (mItemCount > 0 && mSelectedPosition >= 0) { return getChildAt(mSelectedPosition - mFirstPosition); } else { return null; } }
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin. * * @param position Logical position in the list * @param childrenBottomOrTop Top or bottom edge of the view to add * @param flow If flow is true, align top edge to y. If false, align bottom * edge to y. * @param selected Is this position selected? * @return View that was added */ @SuppressWarnings("deprecation") private View makeAndAddView(int position, int childrenBottomOrTop, boolean flow, boolean selected) { View child; int childrenLeft; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned childrenLeft = getItemLeft(position); setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, true); return child; } } //Notify new item is added to view. onItemAddedToList( position, flow ); childrenLeft = getItemLeft( position ); // Make a new view for this position, or convert an unused view if possible DebugUtil.i("makeAndAddView:" + position); child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, mIsScrap[0]); return child; }
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin. * * @param position * Logical position in the list * @param childrenBottomOrTop * Top or bottom edge of the view to add * @param flow * If flow is true, align top edge to y. If false, align bottom * edge to y. * @param childrenLeft * Left edge where children should be positioned * @param selected * Is this position selected? * @return View that was added */ @SuppressWarnings("deprecation") private View makeAndAddView(int position, int childrenBottomOrTop, boolean flow, boolean selected) { View child; int childrenLeft; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned childrenLeft = getItemLeft(position); setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, true); return child; } } // Notify new item is added to view. onItemAddedToList(position, flow); childrenLeft = getItemLeft(position); // Make a new view for this position, or convert an unused view if // possible child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, mIsScrap[0]); return child; }
@Override @TargetApi(Build.VERSION_CODES.LOLLIPOP) public String format(Integer integer, @Nullable ViewDebug.ExportedProperty annotation) { if (annotation != null && annotation.formatToHexString()) { return "0x" + Integer.toHexString(integer); } return super.format(integer, annotation); }
private static boolean isDefaultValue( Integer value, @Nullable ViewDebug.ExportedProperty annotation) { // Mappable ints should always be shown, because enums don't necessarily have // logical "default" values. Thus we mark all of them as not default, so that they // show up in the inspector. if (canFlagsBeMappedToString(annotation) || canIntBeMappedToString(annotation)) { return false; } return value == 0; }
private void getStyleFromFloat( String name, Float value, @Nullable ViewDebug.ExportedProperty annotation, StyleAccumulator styles) { styles.store(name, String.valueOf(value), isDefaultValue(value)); }
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin. * * @param position Logical position in the list * @param childrenBottomOrTop Top or bottom edge of the view to add * @param flow If flow is true, align top edge to y. If false, align bottom * edge to y. * @param selected Is this position selected? * @return View that was added */ @SuppressWarnings("deprecation") private View makeAndAddView(int position, int childrenBottomOrTop, boolean flow, boolean selected) { View child; int childrenLeft; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned childrenLeft = getItemLeft(position); setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, true); return child; } } //Notify new item is added to view. onItemAddedToList( position, flow ); childrenLeft = getItemLeft( position ); // Make a new view for this position, or convert an unused view if possible child = obtainView(position, mIsScrap); // This needs to be positioned and measured setupChild(child, position, childrenBottomOrTop, flow, childrenLeft, selected, mIsScrap[0]); return child; }
/** * Obtain the view and add it to our list of children. The view can be made * fresh, converted from an unused view, or used as is if it was in the * recycle bin. * * @param position Logical position in the list * @param y Top or bottom edge of the view to add * @param flow If flow is true, align top edge to y. If false, align bottom * edge to y. * @param childrenLeft Left edge where children should be positioned * @param selected Is this position selected? * @return View that was added */ private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, boolean selected) { View child; if (!mDataChanged) { // Try to use an exsiting view for this position child = mRecycler.getActiveView(position); // Log.d("TAG", "get active view " + position + " is " + child); if (child != null) { if (ViewDebug.TRACE_RECYCLER) { ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP, position, getChildCount()); } // Found it -- we're using an existing child // This just needs to be positioned setupChild(child, position, y, flow, childrenLeft, selected, true); return child; } } // Make a new view for this position, or convert an unused view if possible // Log.d("TAG", "obtain view " + position); child = obtainView(position, mIsScrap); // Log.d("TAG", "mIsScrap 0 is " + mIsScrap[0]); // This needs to be positioned and measured setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]); return child; }
@ViewDebug.CapturedViewProperty public int getItemId() { return mId; }
@ViewDebug.CapturedViewProperty public CharSequence getTitle() { return mTitle; }
/** * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID} * if nothing is selected. */ @ViewDebug.CapturedViewProperty public long getSelectedItemId() { return mNextSelectedRowId; }
private static boolean canIntBeMappedToString(@Nullable ViewDebug.ExportedProperty annotation) { return annotation != null && annotation.mapping() != null && annotation.mapping().length > 0; }
private static boolean canFlagsBeMappedToString(@Nullable ViewDebug.ExportedProperty annotation) { return annotation != null && annotation.flagMapping() != null && annotation.flagMapping().length > 0; }
private void getStylesFromObject( View view, String name, Object value, @Nullable ViewDebug.ExportedProperty annotation, StyleAccumulator styles) { if (annotation == null || !annotation.deepExport() || value == null) { return; } Field[] fields = value.getClass().getFields(); for (Field field : fields) { int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers)) { continue; } Object propertyValue; try { field.setAccessible(true); propertyValue = field.get(value); } catch (IllegalAccessException e) { LogUtil.e( e, "failed to get property of name: \"" + name + "\" of object: " + String.valueOf(value)); return; } String propertyName = field.getName(); switch (propertyName) { case "bottomMargin": propertyName = "margin-bottom"; break; case "topMargin": propertyName = "margin-top"; break; case "leftMargin": propertyName = "margin-left"; break; case "rightMargin": propertyName = "margin-right"; break; default: String annotationPrefix = annotation.prefix(); propertyName = convertViewPropertyNameToCSSName( (annotationPrefix == null) ? propertyName : (annotationPrefix + propertyName)); break; } ViewDebug.ExportedProperty subAnnotation = field.getAnnotation(ViewDebug.ExportedProperty.class); getStyleFromValue( view, propertyName, propertyValue, subAnnotation, styles); } }
public ViewCSSProperty(String cssName, @Nullable ViewDebug.ExportedProperty annotation) { mCSSName = cssName; mAnnotation = annotation; }
public final @Nullable ViewDebug.ExportedProperty getAnnotation() { return mAnnotation; }
/** * @return The id corresponding to the currently selected item, or INVALID_ROW_ID if nothing is selected. */ @ViewDebug.CapturedViewProperty public long getSelectedItemId() { return mNextSelectedColId; }
/** * @return The number of items owned by the Adapter associated with this AdapterView. (This is the number of data items, which * may be larger than the number of visible views.) */ @ViewDebug.CapturedViewProperty public int getCount() { return mItemCount; }
@ViewDebug.CapturedViewProperty public int getSelectedItemPosition() { return this.mNextSelectedPosition; }
@ViewDebug.CapturedViewProperty public long getSelectedItemId() { return this.mNextSelectedRowId; }
@ViewDebug.CapturedViewProperty public int getCount() { return this.mItemCount; }