aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/relative/DeletionHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/relative/DeletionHandler.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/relative/DeletionHandler.java267
1 files changed, 0 insertions, 267 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/relative/DeletionHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/relative/DeletionHandler.java
deleted file mode 100644
index 3eac510df..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/relative/DeletionHandler.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.android.ide.common.layout.relative;
-
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ATTR_ID;
-import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN;
-import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX;
-import static com.android.SdkConstants.ID_PREFIX;
-import static com.android.SdkConstants.NEW_ID_PREFIX;
-import static com.android.ide.common.layout.BaseViewRule.stripIdPrefix;
-import static com.android.ide.common.layout.relative.ConstraintType.LAYOUT_CENTER_HORIZONTAL;
-import static com.android.ide.common.layout.relative.ConstraintType.LAYOUT_CENTER_VERTICAL;
-
-import com.android.SdkConstants;
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.api.INode;
-import com.android.ide.common.api.INode.IAttribute;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Handles deletions in a relative layout, transferring constraints across
- * deleted nodes
- * <p>
- * TODO: Consider adding the
- * {@link SdkConstants#ATTR_LAYOUT_ALIGN_WITH_PARENT_MISSING} attribute to a
- * node if it's pointing to a node which is deleted and which has no transitive
- * reference to another node.
- */
-public class DeletionHandler {
- private final INode mLayout;
- private final INode[] mChildren;
- private final List<INode> mDeleted;
- private final Set<String> mDeletedIds;
- private final Map<String, INode> mNodeMap;
- private final List<INode> mMoved;
-
- /**
- * Creates a new {@link DeletionHandler}
- *
- * @param deleted the deleted nodes
- * @param moved nodes that were moved (e.g. deleted, but also inserted elsewhere)
- * @param layout the parent layout of the deleted nodes
- */
- public DeletionHandler(@NonNull List<INode> deleted, @NonNull List<INode> moved,
- @NonNull INode layout) {
- mDeleted = deleted;
- mMoved = moved;
- mLayout = layout;
-
- mChildren = mLayout.getChildren();
- mNodeMap = Maps.newHashMapWithExpectedSize(mChildren.length);
- for (INode child : mChildren) {
- String id = child.getStringAttr(ANDROID_URI, ATTR_ID);
- if (id != null) {
- mNodeMap.put(stripIdPrefix(id), child);
- }
- }
-
- mDeletedIds = Sets.newHashSetWithExpectedSize(mDeleted.size());
- for (INode node : mDeleted) {
- String id = node.getStringAttr(ANDROID_URI, ATTR_ID);
- if (id != null) {
- mDeletedIds.add(stripIdPrefix(id));
- }
- }
-
- // Any widgets that remain (e.g. typically because they were moved) should
- // keep their incoming dependencies
- for (INode node : mMoved) {
- String id = node.getStringAttr(ANDROID_URI, ATTR_ID);
- if (id != null) {
- mDeletedIds.remove(stripIdPrefix(id));
- }
- }
- }
-
- @Nullable
- private static String getId(@NonNull IAttribute attribute) {
- if (attribute.getName().startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)
- && ANDROID_URI.equals(attribute.getUri())
- && !attribute.getName().startsWith(ATTR_LAYOUT_MARGIN)) {
- String id = attribute.getValue();
- // It might not be an id reference, so check manually rather than just
- // calling stripIdPrefix():
- if (id.startsWith(NEW_ID_PREFIX)) {
- return id.substring(NEW_ID_PREFIX.length());
- } else if (id.startsWith(ID_PREFIX)) {
- return id.substring(ID_PREFIX.length());
- }
- }
-
- return null;
- }
-
- /**
- * Updates the constraints in the layout to handle deletion of a set of
- * nodes. This ensures that any constraints pointing to one of the deleted
- * nodes are changed properly to point to a non-deleted node with similar
- * constraints.
- */
- public void updateConstraints() {
- if (mChildren.length == mDeleted.size()) {
- // Deleting everything: Nothing to be done
- return;
- }
-
- // Now remove incoming edges to any views that were deleted. If possible,
- // don't just delete them but replace them with a transitive constraint, e.g.
- // if we have "A <= B <= C" and "B" is removed, then we end up with "A <= C",
-
- for (INode child : mChildren) {
- if (mDeleted.contains(child)) {
- continue;
- }
-
- for (IAttribute attribute : child.getLiveAttributes()) {
- String id = getId(attribute);
- if (id != null) {
- if (mDeletedIds.contains(id)) {
- // Unset this reference to a deleted widget. It might be
- // replaced if the pointed to node points to some other node
- // on the same side, but it may use a different constraint name,
- // or have none at all (e.g. parent).
- String name = attribute.getName();
- child.setAttribute(ANDROID_URI, name, null);
-
- INode deleted = mNodeMap.get(id);
- if (deleted != null) {
- ConstraintType type = ConstraintType.fromAttribute(name);
- if (type != null) {
- transfer(deleted, child, type, 0);
- }
- }
- }
- }
- }
- }
- }
-
- private void transfer(INode deleted, INode target, ConstraintType targetType, int depth) {
- if (depth == 20) {
- // Prevent really deep flow or unbounded recursion in case there is a bug in
- // the cycle detection code
- return;
- }
-
- assert mDeleted.contains(deleted);
-
- for (IAttribute attribute : deleted.getLiveAttributes()) {
- String name = attribute.getName();
- ConstraintType type = ConstraintType.fromAttribute(name);
- if (type == null) {
- continue;
- }
-
- ConstraintType transfer = getCompatibleConstraint(type, targetType);
- if (transfer != null) {
- String id = getId(attribute);
- if (id != null) {
- if (mDeletedIds.contains(id)) {
- INode nextDeleted = mNodeMap.get(id);
- if (nextDeleted != null) {
- // Points to another deleted node: recurse
- transfer(nextDeleted, target, targetType, depth + 1);
- }
- } else {
- // Found an undeleted node destination: point to it directly.
- // Note that we're using the
- target.setAttribute(ANDROID_URI, transfer.name, attribute.getValue());
- }
- } else {
- // Pointing to parent or center etc (non-id ref): replicate this on the target
- target.setAttribute(ANDROID_URI, name, attribute.getValue());
- }
- }
- }
- }
-
- /**
- * Determines if two constraints are in the same direction and if so returns
- * the constraint in the same direction. Rather than returning boolean true
- * or false, this returns the constraint which is sometimes modified. For
- * example, if you have a node which points left to a node which is centered
- * in parent, then the constraint is turned into center horizontal.
- */
- @Nullable
- private static ConstraintType getCompatibleConstraint(
- @NonNull ConstraintType first, @NonNull ConstraintType second) {
- if (first == second) {
- return first;
- }
-
- switch (second) {
- case ALIGN_LEFT:
- case LAYOUT_RIGHT_OF:
- switch (first) {
- case LAYOUT_CENTER_HORIZONTAL:
- case LAYOUT_LEFT_OF:
- case ALIGN_LEFT:
- return first;
- case LAYOUT_CENTER_IN_PARENT:
- return LAYOUT_CENTER_HORIZONTAL;
- }
- return null;
-
- case ALIGN_RIGHT:
- case LAYOUT_LEFT_OF:
- switch (first) {
- case LAYOUT_CENTER_HORIZONTAL:
- case ALIGN_RIGHT:
- case LAYOUT_LEFT_OF:
- return first;
- case LAYOUT_CENTER_IN_PARENT:
- return LAYOUT_CENTER_HORIZONTAL;
- }
- return null;
-
- case ALIGN_TOP:
- case LAYOUT_BELOW:
- case ALIGN_BASELINE:
- switch (first) {
- case LAYOUT_CENTER_VERTICAL:
- case ALIGN_TOP:
- case LAYOUT_BELOW:
- case ALIGN_BASELINE:
- return first;
- case LAYOUT_CENTER_IN_PARENT:
- return LAYOUT_CENTER_VERTICAL;
- }
- return null;
- case ALIGN_BOTTOM:
- case LAYOUT_ABOVE:
- switch (first) {
- case LAYOUT_CENTER_VERTICAL:
- case ALIGN_BOTTOM:
- case LAYOUT_ABOVE:
- case ALIGN_BASELINE:
- return first;
- case LAYOUT_CENTER_IN_PARENT:
- return LAYOUT_CENTER_VERTICAL;
- }
- return null;
- }
-
- return null;
- }
-}