use of com.android.ide.common.rendering.api.ViewInfo in project android_frameworks_base by ResurrectionRemix.
the class RenderSessionImpl method createViewInfo.
/**
* Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
* of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
* set.
* @param offset an offset for the view bounds. Used only if view is part of the content frame.
*/
private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo, boolean isContentFrame) {
if (view == null) {
return null;
}
ViewParent parent = view.getParent();
ViewInfo result;
if (isContentFrame) {
// Account for parent scroll values when calculating the bounding box
int scrollX = parent != null ? ((View) parent).getScrollX() : 0;
int scrollY = parent != null ? ((View) parent).getScrollY() : 0;
// The view is part of the layout added by the user. Hence,
// the ViewCookie may be obtained only through the Context.
result = new ViewInfo(view.getClass().getName(), getContext().getViewKey(view), -scrollX + view.getLeft(), -scrollY + view.getTop() + offset, -scrollX + view.getRight(), -scrollY + view.getBottom() + offset, view, view.getLayoutParams());
} else {
// We are part of the system decor.
SystemViewInfo r = new SystemViewInfo(view.getClass().getName(), getViewKey(view), view.getLeft(), view.getTop(), view.getRight(), view.getBottom(), view, view.getLayoutParams());
result = r;
// 3. The overflow popup button.
if (view instanceof ListMenuItemView) {
// Mark 2.
// All menus in the popup are of type ListMenuItemView.
r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
} else {
// Mark 3.
ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp instanceof ActionMenuView.LayoutParams && ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
} else {
// actionProviderClass.
while (parent != mViewRoot && parent instanceof ViewGroup) {
if (parent instanceof ActionMenuView) {
r.setViewType(ViewType.ACTION_BAR_MENU);
break;
}
parent = parent.getParent();
}
}
}
}
if (setExtendedInfo) {
MarginLayoutParams marginParams = null;
LayoutParams params = view.getLayoutParams();
if (params instanceof MarginLayoutParams) {
marginParams = (MarginLayoutParams) params;
}
result.setExtendedInfo(view.getBaseline(), marginParams != null ? marginParams.leftMargin : 0, marginParams != null ? marginParams.topMargin : 0, marginParams != null ? marginParams.rightMargin : 0, marginParams != null ? marginParams.bottomMargin : 0);
}
return result;
}
use of com.android.ide.common.rendering.api.ViewInfo in project android by JetBrains.
the class AttributesTransaction method setAttribute.
@Override
public void setAttribute(@Nullable String namespace, @NotNull String name, @Nullable String value) {
myLock.writeLock().lock();
try {
assert isValid;
String key = attributeKey(namespace, name);
PendingAttribute attribute = myPendingAttributes.get(key);
boolean modified = true;
if (attribute != null) {
if (StringUtil.equals(attribute.value, value)) {
// No change. We do not need to propagate the attribute value to the view
modified = false;
} else {
attribute.value = value;
}
} else {
attribute = new PendingAttribute(namespace, name, value);
myPendingAttributes.put(key, attribute);
}
ViewInfo viewInfo = myComponent.viewInfo;
if (viewInfo != null) {
View cachedView = myCachedView.get();
if (cachedView == viewInfo.getViewObject()) {
// We still have the same view info so we can just apply the delta (the passed attribute)
if (modified && cachedView != null) {
applyAttributeToView(attribute, viewInfo, myModel);
}
} else {
// The view object has changed so we need to re-apply all the attributes
applyAllPendingAttributesToView(viewInfo);
}
}
} finally {
myLock.writeLock().unlock();
}
}
use of com.android.ide.common.rendering.api.ViewInfo in project android by JetBrains.
the class AttributesTransaction method commit.
/**
* Commits all the pending changes to the model. After this method has been called, no more writes or reads can be made from
* this transaction.
*
* @return true if the XML was changed as result of this call
*/
public boolean commit() {
ViewInfo viewInfo = myComponent.viewInfo;
if (hasPendingRelayout && viewInfo != null) {
View currentView = (View) viewInfo.getViewObject();
if (currentView != myCachedView.get()) {
// The view has changed since the last update so re-apply everything
applyAllPendingAttributesToView(myComponent.viewInfo);
}
triggerViewRelayout((View) myComponent.viewInfo.getViewObject());
}
myLock.writeLock().lock();
try {
assert isValid;
if (!myComponent.getTag().isValid()) {
return finishTransaction();
}
if (!ApplicationManager.getApplication().isWriteAccessAllowed()) {
return ApplicationManager.getApplication().runWriteAction((Computable<Boolean>) this::commit);
}
boolean modified = false;
for (PendingAttribute attribute : myPendingAttributes.values()) {
String originalValue = myOriginalValues.get(attributeKey(attribute.namespace, attribute.name));
String currentValue = myComponent.getAttribute(attribute.namespace, attribute.name);
if (!StringUtil.equals(currentValue, attribute.value)) {
// The value has changed from what's in the XML
if (!StringUtil.equals(originalValue, currentValue)) {
// The attribute value has changed since we started the transaction, deal with the conflict.
if (StringUtil.isEmpty(attribute.value)) {
// leave the attribute with the modified value.
continue;
} else if (StringUtil.equals(originalValue, attribute.value)) {
// The attribute has been modified without the change being send through this transaction. Leave the modified value.
continue;
}
}
modified = true;
myComponent.setAttribute(attribute.namespace, attribute.name, attribute.value);
}
}
isSuccessful = true;
finishTransaction();
return modified;
} finally {
myLock.writeLock().unlock();
}
}
use of com.android.ide.common.rendering.api.ViewInfo in project android by JetBrains.
the class ModelBuilder method buildViewInfos.
private List<ViewInfo> buildViewInfos(@NotNull NlModel model) {
List<ViewInfo> infos = Lists.newArrayList();
XmlFile file = model.getFile();
assertThat(file).isNotNull();
assertThat(file.getRootTag()).isNotNull();
infos.add(myRoot.createViewInfo(null, file.getRootTag()));
return infos;
}
use of com.android.ide.common.rendering.api.ViewInfo in project android by JetBrains.
the class NlModelTest method testMoveInHierarchyWithWrongXmlTags.
public void testMoveInHierarchyWithWrongXmlTags() throws Exception {
ModelBuilder modelBuilder = model("linear.xml", component(LINEAR_LAYOUT).withBounds(0, 0, 1000, 1000).matchParentWidth().matchParentHeight().withAttribute(ANDROID_URI, ATTR_ORIENTATION, VALUE_VERTICAL).children(component(FRAME_LAYOUT).withBounds(100, 100, 100, 100).width("100dp").height("100dp").children(component(BUTTON).withBounds(100, 100, 100, 100).width("100dp").height("100dp"))));
NlModel model = modelBuilder.build();
assertEquals("NlComponent{tag=<LinearLayout>, bounds=[0,0:1000x1000, instance=0}\n" + " NlComponent{tag=<FrameLayout>, bounds=[100,100:100x100, instance=1}\n" + " NlComponent{tag=<Button>, bounds=[100,100:100x100, instance=2}", myTreeDumper.toTree(model.getComponents()));
XmlTag originalRoot = model.getFile().getRootTag();
assertThat(originalRoot).isNotNull();
XmlTag originalFrameLayout = originalRoot.getSubTags()[0];
final Project project = model.getProject();
WriteCommandAction.runWriteCommandAction(project, () -> {
PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
Document document = manager.getDocument(model.getFile());
assertThat(document).isNotNull();
document.setText("<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + " android:layout_width=\"match_parent\"\n" + " android:layout_height=\"match_parent\"\n" + " android:orientation=\"vertical\">\n" + " <Button\n" + " android:layout_width=\"100dp\"\n" + " android:layout_height=\"100dp\"\n" + " android:text=\"Button\" />\n" + " <FrameLayout\n" + " android:layout_width=\"100dp\"\n" + " android:layout_height=\"100dp\">\n" + "\n" + " </FrameLayout>\n" + "\n" + "</LinearLayout>");
manager.commitAllDocuments();
});
// Manually construct the view hierarchy
// Assert that component identity is preserved
List<ViewInfo> views = Lists.newArrayList();
XmlTag newRoot = model.getFile().getRootTag();
assertThat(newRoot).isNotNull();
XmlTag[] newRootSubTags = newRoot.getSubTags();
XmlTag newButton = newRootSubTags[0];
assertThat(originalRoot).isSameAs(newRoot);
assertThat(originalFrameLayout).isSameAs(newButton);
TagSnapshot snapshot = TagSnapshot.createTagSnapshot(newRoot);
ViewInfo viewInfo = new ViewInfo("android.widget.LinearLayout", snapshot, 0, 0, 500, 500);
views.add(viewInfo);
ViewInfo buttonInfo = new ViewInfo("android.widget.Button", snapshot.children.get(0), 0, 0, 500, 500);
buttonInfo.setChildren(Collections.emptyList());
ViewInfo frameViewInfo = new ViewInfo("android.widget.TextView", snapshot.children.get(1), 0, 0, 300, 300);
frameViewInfo.setChildren(Collections.emptyList());
viewInfo.setChildren(Arrays.asList(buttonInfo, frameViewInfo));
model.updateHierarchy(newRoot, views);
assertEquals("NlComponent{tag=<LinearLayout>, bounds=[0,0:500x500, instance=3}\n" + // since before the reparse instance=1 was associated with a <FrameLayout> !
" NlComponent{tag=<Button>, bounds=[0,0:500x500, instance=4}\n" + " NlComponent{tag=<FrameLayout>, bounds=[0,0:300x300, instance=5}", myTreeDumper.toTree(model.getComponents()));
}
Aggregations