/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
*
* 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.ide.eclipse.adt.internal.editors.layout.gle2;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.layoutlib.api.ILayoutResult;
import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
import org.eclipse.swt.graphics.Rectangle;
import java.util.ArrayList;
/**
* Maps a {@link ILayoutViewInfo} in a structure more adapted to our needs.
* The only large difference is that we keep both the original bounds of the view info
* and we pre-compute the selection bounds which are absolute to the rendered image (where
* as the original bounds are relative to the parent view.)
* <p/>
* Each view also know its parent, which should be handy later.
* <p/>
* We can't alter {@link ILayoutViewInfo} as it is part of the LayoutBridge and needs to
* have a fixed API.
*/
/* package */ class CanvasViewInfo {
/**
* Minimal size of the selection, in case an empty view or layout is selected.
*/
private static final int SELECTION_MIN_SIZE = 6;
private final Rectangle mAbsRect;
private final Rectangle mSelectionRect;
private final String mName;
private final UiViewElementNode mUiViewKey;
private final CanvasViewInfo mParent;
private final ArrayList<CanvasViewInfo> mChildren = new ArrayList<CanvasViewInfo>();
/**
* Constructs a {@link CanvasViewInfo} hierarchy based on a given {@link ILayoutViewInfo}
* hierarchy. This call is recursive and builds a full tree.
*
* @param viewInfo The root of the {@link ILayoutViewInfo} hierarchy.
*/
public CanvasViewInfo(ILayoutViewInfo viewInfo) {
this(viewInfo, null /*parent*/, 0 /*parentX*/, 0 /*parentY*/);
}
private CanvasViewInfo(ILayoutViewInfo viewInfo, CanvasViewInfo parent, int parentX, int parentY) {
mParent = parent;
mName = viewInfo.getName();
// The ILayoutViewInfo#getViewKey() method returns a key which depends on the
// IXmlPullParser used to parse the layout files. In this case, the parser is
// guaranteed to be an UiElementPullParser, which creates keys that are of type
// UiViewElementNode.
// We'll simply crash if the type is not right, as this is not supposed to happen
// and nothing could work if there's a type mismatch.
mUiViewKey = (UiViewElementNode) viewInfo.getViewKey();
int x = viewInfo.getLeft();
int y = viewInfo.getTop();
int w = viewInfo.getRight() - x;
int h = viewInfo.getBottom() - y;
if (parent != null) {
x += parentX;
y += parentY;
}
mAbsRect = new Rectangle(x, y, w - 1, h - 1);
if (viewInfo.getChildren() != null) {
for (ILayoutViewInfo child : viewInfo.getChildren()) {
mChildren.add(new CanvasViewInfo(child, this, x, y));
}
}
// adjust selection bounds for views which are too small to select
if (w < SELECTION_MIN_SIZE) {
int d = (SELECTION_MIN_SIZE - w) / 2;
x -= d;
w += SELECTION_MIN_SIZE - w;
}
if (h < SELECTION_MIN_SIZE) {
int d = (SELECTION_MIN_SIZE - h) / 2;
y -= d;
h += SELECTION_MIN_SIZE - h;
}
mSelectionRect = new Rectangle(x, y, w - 1, h - 1);
}
/**
* Returns the original {@link ILayoutResult} bounds in absolute coordinates
* over the whole graphic.
*/
public Rectangle getAbsRect() {
return mAbsRect;
}
/*
* Returns the absolute selection bounds of the view info as a rectangle.
* The selection bounds will always have a size greater or equal to
* {@link #SELECTION_MIN_SIZE}.
* The width/height is inclusive (i.e. width = right-left-1).
* This is in absolute "screen" coordinates (relative to the rendered bitmap).
*/
public Rectangle getSelectionRect() {
return mSelectionRect;
}
/**
* Returns the view key. Could be null, although unlikely.
* @return An {@link UiViewElementNode} that uniquely identifies the object in the XML model.
* @see ILayoutViewInfo#getViewKey()
*/
public UiViewElementNode getUiViewKey() {
return mUiViewKey;
}
/**
* Returns the parent {@link CanvasViewInfo}.
* It is null for the root and non-null for children.
*/
public CanvasViewInfo getParent() {
return mParent;
}
/**
* Returns the list of children of this {@link CanvasViewInfo}.
* The list is never null. It can be empty.
* By contract, this.getChildren().get(0..n-1).getParent() == this.
*/
public ArrayList<CanvasViewInfo> getChildren() {
return mChildren;
}
/**
* Returns the name of the {@link CanvasViewInfo}.
* Could be null, although unlikely.
* Experience shows this is the full qualified Java name of the View.
* @see ILayoutViewInfo#getName()
*/
public String getName() {
return mName;
}
}