1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.ide.common.layout.relative; 17 18 import static com.android.ide.common.api.SegmentType.BASELINE; 19 import static com.android.ide.common.api.SegmentType.BOTTOM; 20 import static com.android.ide.common.api.SegmentType.CENTER_HORIZONTAL; 21 import static com.android.ide.common.api.SegmentType.CENTER_VERTICAL; 22 import static com.android.ide.common.api.SegmentType.LEFT; 23 import static com.android.ide.common.api.SegmentType.RIGHT; 24 import static com.android.ide.common.api.SegmentType.TOP; 25 import static com.android.ide.common.api.SegmentType.UNKNOWN; 26 import static com.android.SdkConstants.ATTR_LAYOUT_ABOVE; 27 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_BASELINE; 28 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_BOTTOM; 29 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_LEFT; 30 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_BOTTOM; 31 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_LEFT; 32 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_RIGHT; 33 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_TOP; 34 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_RIGHT; 35 import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_TOP; 36 import static com.android.SdkConstants.ATTR_LAYOUT_BELOW; 37 import static com.android.SdkConstants.ATTR_LAYOUT_CENTER_HORIZONTAL; 38 import static com.android.SdkConstants.ATTR_LAYOUT_CENTER_IN_PARENT; 39 import static com.android.SdkConstants.ATTR_LAYOUT_CENTER_VERTICAL; 40 import static com.android.SdkConstants.ATTR_LAYOUT_TO_LEFT_OF; 41 import static com.android.SdkConstants.ATTR_LAYOUT_TO_RIGHT_OF; 42 43 import com.android.annotations.NonNull; 44 import com.android.annotations.Nullable; 45 import com.android.ide.common.api.SegmentType; 46 47 import java.util.HashMap; 48 import java.util.Map; 49 50 /** 51 * Each constraint type corresponds to a type of constraint available for the 52 * RelativeLayout; for example, {@link #LAYOUT_ABOVE} corresponds to the layout_above constraint. 53 */ 54 enum ConstraintType { 55 LAYOUT_ABOVE(ATTR_LAYOUT_ABOVE, 56 null /* sourceX */, BOTTOM, null /* targetX */, TOP, 57 false /* targetParent */, true /* horizontalEdge */, false /* verticalEdge */, 58 true /* relativeToMargin */), 59 60 LAYOUT_BELOW(ATTR_LAYOUT_BELOW, null, TOP, null, BOTTOM, false, true, false, true), 61 ALIGN_TOP(ATTR_LAYOUT_ALIGN_TOP, null, TOP, null, TOP, false, true, false, false), 62 ALIGN_BOTTOM(ATTR_LAYOUT_ALIGN_BOTTOM, null, BOTTOM, null, BOTTOM, false, true, false, false), 63 ALIGN_LEFT(ATTR_LAYOUT_ALIGN_LEFT, LEFT, null, LEFT, null, false, false, true, false), 64 ALIGN_RIGHT(ATTR_LAYOUT_ALIGN_RIGHT, RIGHT, null, RIGHT, null, false, false, true, false), 65 LAYOUT_LEFT_OF(ATTR_LAYOUT_TO_LEFT_OF, RIGHT, null, LEFT, null, false, false, true, true), 66 LAYOUT_RIGHT_OF(ATTR_LAYOUT_TO_RIGHT_OF, LEFT, null, RIGHT, null, false, false, true, true), 67 ALIGN_PARENT_TOP(ATTR_LAYOUT_ALIGN_PARENT_TOP, null, TOP, null, TOP, true, true, false, false), 68 ALIGN_BASELINE(ATTR_LAYOUT_ALIGN_BASELINE, null, BASELINE, null, BASELINE, false, true, false, 69 false), 70 ALIGN_PARENT_LEFT(ATTR_LAYOUT_ALIGN_PARENT_LEFT, LEFT, null, LEFT, null, true, false, true, 71 false), 72 ALIGN_PARENT_RIGHT(ATTR_LAYOUT_ALIGN_PARENT_RIGHT, RIGHT, null, RIGHT, null, true, false, true, 73 false), 74 ALIGN_PARENT_BOTTOM(ATTR_LAYOUT_ALIGN_PARENT_BOTTOM, null, BOTTOM, null, BOTTOM, true, true, 75 false, false), 76 LAYOUT_CENTER_HORIZONTAL(ATTR_LAYOUT_CENTER_HORIZONTAL, CENTER_VERTICAL, null, CENTER_VERTICAL, 77 null, true, true, false, false), 78 LAYOUT_CENTER_VERTICAL(ATTR_LAYOUT_CENTER_VERTICAL, null, CENTER_HORIZONTAL, null, 79 CENTER_HORIZONTAL, true, false, true, false), 80 LAYOUT_CENTER_IN_PARENT(ATTR_LAYOUT_CENTER_IN_PARENT, CENTER_VERTICAL, CENTER_HORIZONTAL, 81 CENTER_VERTICAL, CENTER_HORIZONTAL, true, true, true, false); 82 ConstraintType(String name, SegmentType sourceSegmentTypeX, SegmentType sourceSegmentTypeY, SegmentType targetSegmentTypeX, SegmentType targetSegmentTypeY, boolean targetParent, boolean horizontalEdge, boolean verticalEdge, boolean relativeToMargin)83 private ConstraintType(String name, SegmentType sourceSegmentTypeX, 84 SegmentType sourceSegmentTypeY, SegmentType targetSegmentTypeX, 85 SegmentType targetSegmentTypeY, boolean targetParent, boolean horizontalEdge, 86 boolean verticalEdge, boolean relativeToMargin) { 87 assert horizontalEdge || verticalEdge; 88 89 this.name = name; 90 this.sourceSegmentTypeX = sourceSegmentTypeX != null ? sourceSegmentTypeX : UNKNOWN; 91 this.sourceSegmentTypeY = sourceSegmentTypeY != null ? sourceSegmentTypeY : UNKNOWN; 92 this.targetSegmentTypeX = targetSegmentTypeX != null ? targetSegmentTypeX : UNKNOWN; 93 this.targetSegmentTypeY = targetSegmentTypeY != null ? targetSegmentTypeY : UNKNOWN; 94 this.targetParent = targetParent; 95 this.horizontalEdge = horizontalEdge; 96 this.verticalEdge = verticalEdge; 97 this.relativeToMargin = relativeToMargin; 98 } 99 100 /** The attribute name of the constraint */ 101 public final String name; 102 103 /** The horizontal position of the source of the constraint */ 104 public final SegmentType sourceSegmentTypeX; 105 106 /** The vertical position of the source of the constraint */ 107 public final SegmentType sourceSegmentTypeY; 108 109 /** The horizontal position of the target of the constraint */ 110 public final SegmentType targetSegmentTypeX; 111 112 /** The vertical position of the target of the constraint */ 113 public final SegmentType targetSegmentTypeY; 114 115 /** 116 * If true, the constraint targets the parent layout, otherwise it targets another 117 * view 118 */ 119 public final boolean targetParent; 120 121 /** If true, this constraint affects the horizontal dimension */ 122 public final boolean horizontalEdge; 123 124 /** If true, this constraint affects the vertical dimension */ 125 public final boolean verticalEdge; 126 127 /** 128 * Whether this constraint is relative to the margin bounds of the node rather than 129 * the node's actual bounds 130 */ 131 public final boolean relativeToMargin; 132 133 /** Map from attribute name to constraint type */ 134 private static Map<String, ConstraintType> sNameToType; 135 136 /** 137 * Returns the {@link ConstraintType} corresponding to the given attribute name, or 138 * null if not found. 139 * 140 * @param attribute the name of the attribute to look up 141 * @return the corresponding {@link ConstraintType} 142 */ 143 @Nullable fromAttribute(@onNull String attribute)144 public static ConstraintType fromAttribute(@NonNull String attribute) { 145 if (sNameToType == null) { 146 ConstraintType[] types = ConstraintType.values(); 147 Map<String, ConstraintType> map = new HashMap<String, ConstraintType>(types.length); 148 for (ConstraintType type : types) { 149 map.put(type.name, type); 150 } 151 sNameToType = map; 152 } 153 return sNameToType.get(attribute); 154 } 155 156 /** 157 * Returns true if this constraint type represents a constraint where the target edge 158 * is one of the parent edges (actual edge, not center/baseline segments) 159 * 160 * @return true if the target segment is a parent edge 161 */ isRelativeToParentEdge()162 public boolean isRelativeToParentEdge() { 163 return this == ALIGN_PARENT_LEFT || this == ALIGN_PARENT_RIGHT || this == ALIGN_PARENT_TOP 164 || this == ALIGN_PARENT_BOTTOM; 165 } 166 167 /** 168 * Returns a {@link ConstraintType} for a potential match of edges. 169 * 170 * @param withParent if true, the target is the parent 171 * @param from the source edge 172 * @param to the target edge 173 * @return a {@link ConstraintType}, or null 174 */ 175 @Nullable forMatch(boolean withParent, SegmentType from, SegmentType to)176 public static ConstraintType forMatch(boolean withParent, SegmentType from, SegmentType to) { 177 // Attached to parent edge? 178 if (withParent) { 179 switch (from) { 180 case TOP: 181 return ALIGN_PARENT_TOP; 182 case BOTTOM: 183 return ALIGN_PARENT_BOTTOM; 184 case LEFT: 185 return ALIGN_PARENT_LEFT; 186 case RIGHT: 187 return ALIGN_PARENT_RIGHT; 188 case CENTER_HORIZONTAL: 189 return LAYOUT_CENTER_VERTICAL; 190 case CENTER_VERTICAL: 191 return LAYOUT_CENTER_HORIZONTAL; 192 } 193 194 return null; 195 } 196 197 // Attached to some other node. 198 switch (from) { 199 case TOP: 200 switch (to) { 201 case TOP: 202 return ALIGN_TOP; 203 case BOTTOM: 204 return LAYOUT_BELOW; 205 case BASELINE: 206 return ALIGN_BASELINE; 207 } 208 break; 209 case BOTTOM: 210 switch (to) { 211 case TOP: 212 return LAYOUT_ABOVE; 213 case BOTTOM: 214 return ALIGN_BOTTOM; 215 case BASELINE: 216 return ALIGN_BASELINE; 217 } 218 break; 219 case LEFT: 220 switch (to) { 221 case LEFT: 222 return ALIGN_LEFT; 223 case RIGHT: 224 return LAYOUT_RIGHT_OF; 225 } 226 break; 227 case RIGHT: 228 switch (to) { 229 case LEFT: 230 return LAYOUT_LEFT_OF; 231 case RIGHT: 232 return ALIGN_RIGHT; 233 } 234 break; 235 case BASELINE: 236 return ALIGN_BASELINE; 237 } 238 239 return null; 240 } 241 } 242