diff options
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.java | 267 |
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; - } -} |