/* * 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.android.SdkConstants; import com.intellij.android.designer.AndroidDesignerUtils; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.designer.designSurface.EditableArea; import org.jetbrains.annotations.Nullable; import java.awt.*; import static com.android.SdkConstants.*; /** State held during resizing operations */ public class ResizeContext { private final EditableArea myArea; /** * The node being resized */ public final RadViewComponent node; /** * The layout containing the resized node */ public final RadViewComponent layout; /** The proposed resized bounds of the node */ public Rectangle bounds; /** The preferred wrap_content bounds of the node */ public Dimension wrapSize; /** The match parent bounds of the node */ public Dimension fillSize; /** The suggested horizontal fill_parent guideline position */ public Segment horizontalFillSegment; /** The suggested vertical fill_parent guideline position */ public Segment verticalFillSegment; /** The type of horizontal edge being resized, or null */ public SegmentType horizontalEdgeType; /** The type of vertical edge being resized, or null */ public SegmentType verticalEdgeType; /** Whether the user has snapped to the wrap_content width */ public boolean wrapWidth; /** Whether the user has snapped to the wrap_content height */ public boolean wrapHeight; /** Whether the user has snapped to the match_parent width */ public boolean fillWidth; /** Whether the user has snapped to the match_parent height */ public boolean fillHeight; /** Custom field for use by subclasses */ public Object clientData; /** Keyboard mask */ public int modifierMask; /** * The actual view object for the layout containing the resizing operation, * or null if not known */ @Nullable public Object layoutView; /** * Constructs a new {@link ResizeContext} * * @param area the associated area * @param layout the parent layout containing the resized node * @param layoutView the actual View instance for the layout, or null if not known * @param node the node being resized */ ResizeContext(EditableArea area, RadViewComponent layout, @Nullable Object layoutView, RadViewComponent node) { myArea = area; this.layout = layout; this.node = node; this.layoutView = layoutView; initializeSnapBounds(); } protected void initializeSnapBounds() { wrapSize = node.calculateWrapSize(myArea); String width = node.getAttribute(ATTR_LAYOUT_WIDTH, SdkConstants.NS_RESOURCES); String height = node.getAttribute(ATTR_LAYOUT_HEIGHT, SdkConstants.NS_RESOURCES); fillSize = new Dimension(); Rectangle bounds = node.getBounds(); Rectangle parentBounds = node.getParent().getBounds(); if (width != null && isFill(width)) { // Already have the fill bounds since view specifies match parent already fillSize.width = bounds.width; } else { // TODO: Subtract padding too? fillSize.width = parentBounds.x + parentBounds.width - bounds.x; } if (height != null && isFill(height)) { // Already have the fill bounds since view specifies match parent already fillSize.height = bounds.height; } else { // TODO: Subtract padding too? fillSize.height = parentBounds.y + parentBounds.height - bounds.y; } // If fillSize and wrapSize are identical, space them out a bit to let the user select each if (fillSize.width == wrapSize.width) { fillSize.width += 5; } if (fillSize.height == wrapSize.height) { fillSize.height += 5; } } public static boolean isFill(String value) { return VALUE_FILL_PARENT.equals(value) || VALUE_MATCH_PARENT.equals(value); } /** * Returns the width attribute to be set to match the new bounds * * @return the width string, never null */ public String getWidthAttribute() { if (wrapWidth) { return VALUE_WRAP_CONTENT; } else if (fillWidth) { //return mRule.getFillParentValueName(); return VALUE_MATCH_PARENT; } else { return AndroidDesignerUtils.pxToDpWithUnits(myArea, bounds.width); } } /** * Returns the height attribute to be set to match the new bounds * * @return the height string, never null */ public String getHeightAttribute() { if (wrapHeight) { return VALUE_WRAP_CONTENT; } else if (fillHeight) { //return mRule.getFillParentValueName(); return VALUE_MATCH_PARENT; } else { return AndroidDesignerUtils.pxToDpWithUnits(myArea, bounds.height); } } }