blob: 7e08af9ae500cae572845983db6c771d8e891f3d [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.tools.idea.designer;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.android.designer.model.layout.TextDirection;
import com.intellij.designer.utils.Position;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
/**
* A segment type describes the different roles or positions a segment can have in a node
*/
public enum SegmentType {
/**
* Segment is on start side (left if LTR, right if RTL).
*/
@NotNull START,
/**
* Segment is on end side (right if LTR, left if RTL).
*/
@NotNull END,
/**
* Segment is on the left edge
*/
@NotNull LEFT,
/**
* Segment is on the top edge
*/
@NotNull TOP,
/**
* Segment is on the right edge
*/
@NotNull RIGHT,
/**
* Segment is on the bottom edge
*/
@NotNull BOTTOM,
/**
* Segment is along the baseline
*/
@NotNull BASELINE,
/**
* Segment is along the center vertically
*/
@NotNull CENTER_VERTICAL,
/**
* Segment is along the center horizontally
*/
@NotNull CENTER_HORIZONTAL,
/**
* Segment is on an unknown edge
*/
@NotNull UNKNOWN;
public boolean isHorizontal() {
return this == TOP || this == BOTTOM || this == BASELINE || this == CENTER_HORIZONTAL;
}
/**
* Returns the X coordinate for an edge of this type given its bounds
*
* @param node the node containing the edge
* @param bounds the bounds of the node
* @return the X coordinate for an edge of this type given its bounds
*/
public int getX(@NotNull TextDirection textDirection,
@SuppressWarnings("UnusedParameters") @Nullable RadViewComponent node,
@NotNull Rectangle bounds) {
SegmentType me = this;
switch(this) {
case START:
me = textDirection == TextDirection.RIGHT_TO_LEFT ? RIGHT : LEFT;
break;
case END:
me = textDirection == TextDirection.RIGHT_TO_LEFT ? LEFT : RIGHT;
break;
}
// We pass in the bounds rather than look it up via node.getBounds() because
// during a resize or move operation, we call this method to look up proposed
// bounds rather than actual bounds
switch (me) {
case RIGHT:
return bounds.x + bounds.width;
case TOP:
case BOTTOM:
case CENTER_VERTICAL:
return bounds.x + bounds.width / 2;
case UNKNOWN:
assert false;
return bounds.x;
case LEFT:
case BASELINE:
default:
return bounds.x;
}
}
/**
* Returns the Y coordinate for an edge of this type given its bounds
*
* @param node the node containing the edge
* @param bounds the bounds of the node
* @return the Y coordinate for an edge of this type given its bounds
*/
public int getY(@Nullable RadViewComponent node, @NotNull Rectangle bounds) {
switch (this) {
case TOP:
return bounds.y;
case BOTTOM:
return bounds.y + bounds.height;
case BASELINE: {
int baseline = node != null ? node.getBaseline() : -1;
if (node == null) {
// This happens when you are dragging an element and we don't have
// a node such as on a palette drag. For now just hack it.
baseline = (int)(bounds.height * 0.8f); // HACK
}
return bounds.y + baseline;
}
case UNKNOWN:
assert false;
return bounds.y;
case RIGHT:
case LEFT:
case CENTER_HORIZONTAL:
default:
return bounds.y + bounds.height / 2;
}
}
@Override
public String toString() {
return name();
}
@Nullable
public static SegmentType getHorizontalResizeEdge(int direction) {
switch (direction) {
case Position.SOUTH: {
return BOTTOM;
}
case Position.NORTH: {
return TOP;
}
case Position.NORTH_EAST: {
return TOP;
}
case Position.SOUTH_EAST: {
return BOTTOM;
}
case Position.NORTH_WEST: {
return TOP;
}
case Position.SOUTH_WEST: {
return BOTTOM;
}
case Position.NORTH_SOUTH:
case Position.EAST_WEST:
// Shouldn't be used in resizing operations
assert false : direction;
return null;
default:
return null;
}
}
@Nullable
public static SegmentType getVerticalResizeEdge(int direction) {
switch (direction) {
case Position.EAST: {
return RIGHT;
}
case Position.WEST: {
return LEFT;
}
case Position.NORTH_EAST: {
return RIGHT;
}
case Position.SOUTH_EAST: {
return RIGHT;
}
case Position.NORTH_WEST: {
return LEFT;
}
case Position.SOUTH_WEST: {
return LEFT;
}
case Position.NORTH_SOUTH:
case Position.EAST_WEST:
// Shouldn't be used in resizing operations
assert false : direction;
return null;
default:
return null;
}
}
}