blob: 256dc09c296e3197adca4dd80d81e8400a0a4186 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.intellij.android.designer.model.layout.relative;
import com.android.tools.idea.designer.SegmentType;
import com.intellij.android.designer.designSurface.feedbacks.TextFeedback;
import com.intellij.android.designer.designSurface.graphics.DirectionResizePoint;
import com.intellij.android.designer.designSurface.graphics.DrawingStyle;
import com.intellij.android.designer.designSurface.graphics.ResizeSelectionDecorator;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.FeedbackLayer;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.utils.Position;
import com.intellij.openapi.application.ApplicationManager;
import java.awt.*;
import java.util.List;
import static com.android.SdkConstants.*;
public class RelativeLayoutResizeOperation implements EditOperation {
public static final String TYPE = "relative_resize";
private final OperationContext myContext;
private RadViewComponent myComponent;
private RadViewComponent myContainer;
private GuidelinePainter myFeedback;
private ResizeHandler myResizeHandler;
private MultiLineTooltipManager myTooltip;
public RelativeLayoutResizeOperation(OperationContext context) {
myContext = context;
}
@Override
public void setComponent(RadComponent component) {
myComponent = (RadViewComponent)component;
myContainer = (RadViewComponent)myComponent.getParent();
}
@Override
public void setComponents(List<RadComponent> components) {
assert components.size() == 1 : components;
myComponent = (RadViewComponent)components.get(0);
myContainer = (RadViewComponent)myComponent.getParent();
}
@Override
public void showFeedback() {
if (myFeedback == null) {
SegmentType horizontalEdgeType = null;
SegmentType verticalEdgeType = null;
int direction = myContext.getResizeDirection();
if ((direction & Position.NORTH) != 0) {
horizontalEdgeType = SegmentType.TOP;
}
if ((direction & Position.SOUTH) != 0) {
horizontalEdgeType = SegmentType.BOTTOM;
}
if ((direction & Position.WEST) != 0) {
verticalEdgeType = SegmentType.LEFT;
}
if ((direction & Position.EAST) != 0) {
verticalEdgeType = SegmentType.RIGHT;
}
myResizeHandler = new ResizeHandler(myContainer, myComponent, myContext, horizontalEdgeType, verticalEdgeType);
myFeedback = new GuidelinePainter(myResizeHandler);
FeedbackLayer layer = myContext.getArea().getFeedbackLayer();
layer.add(myFeedback);
myFeedback.setBounds(0, 0, layer.getWidth(), layer.getHeight());
myTooltip = new MultiLineTooltipManager(layer, 4);
}
Rectangle bounds = myContext.getTransformedRectangle(myComponent.getBounds(myContext.getArea().getFeedbackLayer()));
bounds.width = Math.max(bounds.width, 0);
bounds.height = Math.max(bounds.height, 0);
myResizeHandler.updateResize(myComponent, bounds, myContext.getModifiers());
myFeedback.repaint();
// Update the text
describeMatch(myResizeHandler.getCurrentLeftMatch(), 0, myResizeHandler.getLeftMarginDp(), ATTR_LAYOUT_MARGIN_LEFT);
describeMatch(myResizeHandler.getCurrentRightMatch(), 1, myResizeHandler.getRightMarginDp(), ATTR_LAYOUT_MARGIN_RIGHT);
describeMatch(myResizeHandler.getCurrentTopMatch(), 2, myResizeHandler.getTopMarginDp() , ATTR_LAYOUT_MARGIN_TOP);
describeMatch(myResizeHandler.getCurrentBottomMatch(), 3, myResizeHandler.getBottomMarginDp(), ATTR_LAYOUT_MARGIN_BOTTOM);
// Position the tooltip
Point location = myContext.getLocation();
myTooltip.update(myContainer, location);
}
private void describeMatch(Match m, int line, int margin, String marginAttribute) {
if (m == null) {
myTooltip.setVisible(line, false);
return;
}
myTooltip.setVisible(line, true);
TextFeedback feedback = myTooltip.getFeedback(line);
m.describe(feedback, margin, marginAttribute);
}
@Override
public void eraseFeedback() {
if (myFeedback != null) {
FeedbackLayer layer = myContext.getArea().getFeedbackLayer();
layer.remove(myFeedback);
myTooltip.dispose();
myFeedback = null;
myTooltip = null;
layer.repaint();
}
}
@Override
public boolean canExecute() {
return true;
}
@Override
public void execute() throws Exception {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
myResizeHandler.removeCycles();
myResizeHandler.applyConstraints(myComponent);
}
});
}
public static void addResizePoints(ResizeSelectionDecorator decorator) {
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.NORTH_WEST, TYPE,
"Change layout:width x layout:height, top x left alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.NORTH, TYPE, "Change layout:height, top alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.NORTH_EAST, TYPE,
"Change layout:width x layout:height, top x right alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.EAST, TYPE, "Change layout:width, right alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.SOUTH_EAST, TYPE,
"Change layout:width x layout:height, bottom x right alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.SOUTH, TYPE,
"Change layout:height, bottom alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.SOUTH_WEST, TYPE,
"Change layout:width x layout:height, bottom x left alignment"));
decorator.addPoint(new DirectionResizePoint(DrawingStyle.SELECTION, Position.WEST, TYPE, "Change layout:width, left alignment"));
}
}