ShadowView.java revision 8de53d85207b90879fd242796941d526277b1245
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)package com.xtremelabs.robolectric.shadows;
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.content.Context;
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.content.res.Resources;
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.util.AttributeSet;
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.view.MotionEvent;
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.view.View;
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.view.ViewGroup;
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import android.view.ViewParent;
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import com.xtremelabs.robolectric.util.Implementation;
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import com.xtremelabs.robolectric.util.Implements;
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import com.xtremelabs.robolectric.util.RealObject;
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.io.PrintStream;
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.util.HashMap;
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.util.Map;
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import static com.xtremelabs.robolectric.Robolectric.shadowOf;
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Shadow implementation of {@code View} that simulates the behavior of this class. Supports listeners, focusability
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (but not focus order), resource loading, visibility, tags, and tracks the size and shape of the view.
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@SuppressWarnings({"UnusedDeclaration"})
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)@Implements(View.class)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public class ShadowView {
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Deprecated
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public static final int UNINITIALIZED_ATTRIBUTE = -1000;
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    @RealObject protected View realView;
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    private int id;
33e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ShadowView parent;
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private Context context;
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private boolean selected;
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private View.OnClickListener onClickListener;
37df95704c49daea886ddad70775bda23618d6274dBen Murdoch    private Object tag;
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private boolean enabled = true;
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private int visibility = View.VISIBLE;
40e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    int left;
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int top;
42e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    int right;
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    int bottom;
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private int paddingLeft;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private int paddingTop;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private int paddingRight;
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private int paddingBottom;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(0, 0);
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private Map<Integer, Object> tags = new HashMap<Integer, Object>();
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private boolean clickable;
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected boolean focusable;
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    boolean focusableInTouchMode;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private int backgroundResourceId = -1;
54591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    protected View.OnKeyListener onKeyListener;
55591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    private boolean isFocused;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private View.OnFocusChangeListener onFocusChangeListener;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private boolean wasInvalidated;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private View.OnTouchListener onTouchListener;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void __constructor__(Context context) {
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.context = context;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
63df95704c49daea886ddad70775bda23618d6274dBen Murdoch
64c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    public void __constructor__(Context context, AttributeSet attrs) {
65c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)        __constructor__(context);
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setId(int id) {
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.id = id;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setClickable(boolean clickable) {
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.clickable = clickable;
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Also sets focusable in touch mode to false if {@code focusable} is false, which is the Android behavior.
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     *
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param focusable the new status of the {@code View}'s focusability
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setFocusable(boolean focusable) {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.focusable = focusable;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!focusable) {
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            setFocusableInTouchMode(false);
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
90df95704c49daea886ddad70775bda23618d6274dBen Murdoch
91df95704c49daea886ddad70775bda23618d6274dBen Murdoch    @Implementation
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public final boolean isFocusableInTouchMode() {
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return focusableInTouchMode;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Also sets focusable to true if {@code focusableInTouchMode} is true, which is the Android behavior.
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     *
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param focusableInTouchMode the new status of the {@code View}'s touch mode focusability
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.focusableInTouchMode = focusableInTouchMode;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (focusableInTouchMode) {
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            setFocusable(true);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
11002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    public boolean isFocusable() {
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return focusable;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
114df95704c49daea886ddad70775bda23618d6274dBen Murdoch    @Implementation
115df95704c49daea886ddad70775bda23618d6274dBen Murdoch    public int getId() {
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return id;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Simulates the inflating of the requested resource.
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     *
12202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch     * @param context  the context from which to obtain a layout inflater
123591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param resource the ID of the resource to inflate
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param root     the {@code ViewGroup} to add the inflated {@code View} to
12502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch     * @return the inflated View
12602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch     */
12702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    @Implementation
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public static View inflate(Context context, int resource, ViewGroup root) {
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        View view = ShadowLayoutInflater.from(context).inflate(resource, root);
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (root != null) {
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            root.addView(view);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return view;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Finds this {@code View} if it's ID is passed in, returns {@code null} otherwise
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     *
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param id the id of the {@code View} to find
140591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @return the {@code View}, if found, {@code null} otherwise
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public View findViewById(int id) {
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (id == this.id) {
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return realView;
14602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        }
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public View getRootView() {
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ShadowView root = this;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (root.parent != null) {
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            root = root.parent;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return root.realView;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public ViewGroup.LayoutParams getLayoutParams() {
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return layoutParams;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setLayoutParams(ViewGroup.LayoutParams params) {
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        layoutParams = params;
168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public final ViewParent getParent() {
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return parent == null ? null : (ViewParent) parent.realView;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public final Context getContext() {
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return context;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public Resources getResources() {
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return context.getResources();
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setBackgroundResource(int backgroundResourceId) {
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.backgroundResourceId = backgroundResourceId;
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
19053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    @Implementation
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public int getVisibility() {
192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return visibility;
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    @Implementation
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    public void setVisibility(int visibility) {
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.visibility = visibility;
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    public void setSelected(boolean selected) {
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.selected = selected;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public boolean isSelected() {
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this.selected;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    @Implementation
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public boolean isEnabled() {
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this.enabled;
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2150019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    @Implementation
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setEnabled(boolean enabled) {
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.enabled = enabled;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    @Implementation
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public void setOnClickListener(View.OnClickListener onClickListener) {
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.onClickListener = onClickListener;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
224
225    @Implementation
226    public boolean performClick() {
227        if (onClickListener != null) {
228            onClickListener.onClick(realView);
229            return true;
230        } else {
231            return false;
232        }
233    }
234
235    @Implementation
236    public void setOnKeyListener(View.OnKeyListener onKeyListener) {
237        this.onKeyListener = onKeyListener;
238    }
239
240    @Implementation
241    public Object getTag() {
242        return this.tag;
243    }
244
245    @Implementation
246    public void setTag(Object tag) {
247        this.tag = tag;
248    }
249
250    @Implementation
251    public final int getHeight() {
252        return bottom - top;
253    }
254
255    @Implementation
256    public final int getWidth() {
257        return right - left;
258    }
259
260    @Implementation
261    public final int getMeasuredWidth() {
262        return getWidth();
263    }
264
265    @Implementation
266    public final void layout(int l, int t, int r, int b) {
267        left = l;
268        top = t;
269        right = r;
270        bottom = b;
271
272// todo:       realView.onLayout();
273    }
274
275    @Implementation
276    public void setPadding(int left, int top, int right, int bottom) {
277        paddingLeft = left;
278        paddingTop = top;
279        paddingRight = right;
280        paddingBottom = bottom;
281    }
282
283    @Implementation
284    public int getPaddingTop() {
285        return paddingTop;
286    }
287
288    @Implementation
289    public int getPaddingLeft() {
290        return paddingLeft;
291    }
292
293    @Implementation
294    public int getPaddingRight() {
295        return paddingRight;
296    }
297
298    @Implementation
299    public int getPaddingBottom() {
300        return paddingBottom;
301    }
302
303    @Implementation
304    public Object getTag(int key) {
305        return tags.get(key);
306    }
307
308    @Implementation
309    public void setTag(int key, Object value) {
310        tags.put(key, value);
311    }
312
313    @Implementation
314    public final boolean requestFocus() {
315        return requestFocus(View.FOCUS_DOWN);
316    }
317
318    @Implementation
319    public final boolean requestFocus(int direction) {
320        setViewFocus(true);
321        return true;
322    }
323
324    public void setViewFocus(boolean hasFocus) {
325        this.isFocused = hasFocus;
326        if (onFocusChangeListener != null) {
327            onFocusChangeListener.onFocusChange(realView, hasFocus);
328        }
329    }
330
331    @Implementation
332    public boolean isFocused() {
333        return isFocused;
334    }
335
336    @Implementation
337    public boolean hasFocus() {
338        return isFocused;
339    }
340
341    @Implementation
342    public void clearFocus() {
343        setViewFocus(false);
344    }
345
346    @Implementation
347    public void setOnFocusChangeListener(View.OnFocusChangeListener listener) {
348        onFocusChangeListener = listener;
349    }
350
351    @Implementation
352    public void invalidate() {
353        wasInvalidated = true;
354    }
355
356    @Implementation
357    public void setOnTouchListener(View.OnTouchListener onTouchListener) {
358        this.onTouchListener = onTouchListener;
359    }
360
361    @Implementation
362    public boolean dispatchTouchEvent(MotionEvent event) {
363        if (onTouchListener != null) {
364            return onTouchListener.onTouch(realView, event);
365        }
366        return false;
367    }
368
369    /**
370     * Returns a string representation of this {@code View}. Unless overridden, it will be an empty string.
371     *
372     * Robolectric extension.
373     */
374    public String innerText() {
375        return "";
376    }
377
378    /**
379     * Dumps the status of this {@code View} to {@code System.out}
380     */
381    public void dump() {
382        dump(System.out, 0);
383    }
384
385    /**
386     * Dumps the status of this {@code View} to {@code System.out} at the given indentation level
387     */
388    public void dump(PrintStream out, int indent) {
389        dumpFirstPart(out, indent);
390        out.println("/>");
391    }
392
393    protected void dumpFirstPart(PrintStream out, int indent) {
394        dumpIndent(out, indent);
395
396        out.print("<" + realView.getClass().getSimpleName());
397        if (id > 0) {
398            out.print(" id=\"" + shadowOf(context).getResourceLoader().getNameForId(id) + "\"");
399        }
400    }
401
402    protected void dumpIndent(PrintStream out, int indent) {
403        for (int i = 0; i < indent; i++) out.print(" ");
404    }
405
406    /**
407     * @return left side of the view
408     */
409    @Implementation
410    public int getLeft() {
411        return left;
412    }
413
414    /**
415     * @return top coordinate of the view
416     */
417    @Implementation
418    public int getTop() {
419        return top;
420    }
421
422    /**
423     * @return right side of the view
424     */
425    @Implementation
426    public int getRight() {
427        return right;
428    }
429
430    /**
431     * @return bottom coordinate of the view
432     */
433    @Implementation
434    public int getBottom() {
435        return bottom;
436    }
437
438    /**
439     * @return whether the view is clickable
440     */
441    @Implementation
442    public boolean isClickable() {
443        return clickable;
444    }
445
446    /**
447     * Non-Android accessor.
448     *
449     * @return the resource ID of this views background
450     */
451    public int getBackgroundResourceId() {
452        return backgroundResourceId;
453    }
454
455    /**
456     * Non-Android accessor.
457     *
458     * @return whether or not {@link #invalidate()} has been called
459     */
460    public boolean wasInvalidated() {
461        return wasInvalidated;
462    }
463
464    /**
465     * Clears the wasInvalidated flag
466     */
467    public void clearWasInvalidated() {
468        wasInvalidated = false;
469    }
470
471    /**
472     * Non-Android accessor.
473     */
474    public void setLeft(int left) {
475        this.left = left;
476    }
477
478    /**
479     * Non-Android accessor.
480     */
481    public void setTop(int top) {
482        this.top = top;
483    }
484
485    /**
486     * Non-Android accessor.
487     */
488    public void setRight(int right) {
489        this.right = right;
490    }
491
492    /**
493     * Non-Android accessor.
494     */
495    public void setBottom(int bottom) {
496        this.bottom = bottom;
497    }
498
499    /**
500     * Non-Android accessor.
501     */
502    public void setPaddingLeft(int paddingLeft) {
503        this.paddingLeft = paddingLeft;
504    }
505
506    /**
507     * Non-Android accessor.
508     */
509    public void setPaddingTop(int paddingTop) {
510        this.paddingTop = paddingTop;
511    }
512
513    /**
514     * Non-Android accessor.
515     */
516    public void setPaddingRight(int paddingRight) {
517        this.paddingRight = paddingRight;
518    }
519
520    /**
521     * Non-Android accessor.
522     */
523    public void setPaddingBottom(int paddingBottom) {
524        this.paddingBottom = paddingBottom;
525    }
526
527    /**
528     * Non-Android accessor.
529     */
530    public void setFocused(boolean focused) {
531        isFocused = focused;
532    }
533
534    /**
535     * Non-Android accessor.
536     *
537     * @return true if this object and all of its ancestors are {@code View.VISIBLE}, returns false if this or
538     *         any ancestor is not {@code View.VISIBLE}
539     */
540    public boolean derivedIsVisible() {
541        View parent = realView;
542        while (parent != null) {
543            if (parent.getVisibility() != View.VISIBLE) {
544                return false;
545            }
546            parent = (View) parent.getParent();
547        }
548        return true;
549    }
550}
551