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 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 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 */ 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 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