| /* |
| * 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")); |
| } |
| } |