/* * 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.rendering; import com.android.ide.common.rendering.api.ViewInfo; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import com.intellij.psi.xml.XmlTag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.Collections; import java.util.Iterator; import java.util.List; public class RenderedView implements Iterable<RenderedView> { @Nullable public final RenderedView parent; @Nullable public final XmlTag tag; public final ViewInfo view; public final int x; public final int y; public final int w; public final int h; private List<RenderedView> myChildren; public RenderedView(@Nullable RenderedView parent, @Nullable ViewInfo view, @Nullable XmlTag tag, int x, int y, int w, int h) { this.parent = parent; this.view = view; this.x = x; this.y = y; this.w = w; this.h = h; this.tag = tag; } public final int x2() { return x + w; } public final int y2() { return y + h; } @Nullable public RenderedView getParent() { return parent; } public void setChildren(List<RenderedView> children) { myChildren = children; } @NotNull public List<RenderedView> getChildren() { return myChildren != null ? myChildren : Collections.<RenderedView>emptyList(); } @Nullable public RenderedView findViewByTag(XmlTag tag) { if (this.tag == tag) { return this; } if (myChildren != null) { for (RenderedView child : myChildren) { RenderedView result = child.findViewByTag(tag); if (result != null) { return result; } } } return null; } @Nullable public List<RenderedView> findViewsByTag(XmlTag tag) { if (this.tag == tag) { //return Lists.newArrayList(this); List<RenderedView> list = Lists.newArrayList(); list.add(this); return list; } List<RenderedView> result = null; if (myChildren != null) { for (RenderedView child : myChildren) { List<RenderedView> matches = child.findViewsByTag(tag); if (matches != null) { if (result != null) { result.addAll(matches); } else { result = matches; } } } } return result; } @Nullable public RenderedView findLeafAt(int px, int py) { if (myChildren != null) { // Search BACKWARDS such that if the children are painted on top of each // other (as is the case in a FrameLayout) I pick the last one which will // be topmost! for (int i = myChildren.size() - 1; i >= 0; i--) { RenderedView child = myChildren.get(i); RenderedView result = child.findLeafAt(px, py); if (result != null) { return result; } } } return (x <= px && y <= py && x + w >= px && y + h >= py) ? this : null; } public boolean isRoot() { return tag == null || !(tag.getParent() instanceof XmlTag); } // ---- Implements Iterable<RenderedView> ---- @Override public Iterator<RenderedView> iterator() { if (myChildren == null) { return Iterators.emptyIterator(); } return myChildren.iterator(); } public Rectangle getBounds() { return new Rectangle(x, y, w, h); } }