Home | History | Annotate | Download | only in shadows
      1 package com.xtremelabs.robolectric.shadows;
      2 
      3 import android.app.Activity;
      4 import android.app.Dialog;
      5 import android.content.Context;
      6 import android.content.DialogInterface;
      7 import android.os.Bundle;
      8 import android.view.LayoutInflater;
      9 import android.view.View;
     10 import android.view.ViewGroup;
     11 import android.view.Window;
     12 import com.xtremelabs.robolectric.Robolectric;
     13 import com.xtremelabs.robolectric.internal.Implementation;
     14 import com.xtremelabs.robolectric.internal.Implements;
     15 import com.xtremelabs.robolectric.internal.RealObject;
     16 import com.xtremelabs.robolectric.tester.android.view.TestWindow;
     17 
     18 import java.lang.reflect.Method;
     19 import java.util.ArrayList;
     20 import java.util.List;
     21 
     22 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
     23 
     24 @SuppressWarnings({"UnusedDeclaration"})
     25 @Implements(Dialog.class)
     26 public class ShadowDialog {
     27 
     28     @RealObject private Dialog realDialog;
     29 
     30     private boolean isShowing;
     31     Context context;
     32     private int layoutId;
     33     private int themeId;
     34     private View inflatedView;
     35     private boolean hasBeenDismissed;
     36     private DialogInterface.OnDismissListener onDismissListener;
     37     protected CharSequence title;
     38     private DialogInterface.OnCancelListener onCancelListener;
     39     private Window window;
     40     private Activity ownerActivity;
     41     private boolean isCancelable = true;
     42     private boolean hasShownBefore;
     43     private static final ArrayList<Dialog> shownDialogs = new ArrayList<Dialog>();
     44     private boolean isCancelableOnTouchOutside;
     45 
     46     public static void reset() {
     47         setLatestDialog(null);
     48         shownDialogs.clear();
     49     }
     50 
     51     public static Dialog getLatestDialog() {
     52         ShadowDialog dialog = Robolectric.getShadowApplication().getLatestDialog();
     53         return dialog == null ? null : dialog.realDialog;
     54     }
     55 
     56     public static void setLatestDialog(ShadowDialog latestDialog) {
     57         Robolectric.getShadowApplication().setLatestDialog(latestDialog);
     58     }
     59 
     60     public void __constructor__(Context context) {
     61         __constructor__(context, -1);
     62     }
     63 
     64     public void __constructor__(Context context, int themeId) {
     65         this.context = context;
     66         this.themeId = themeId;
     67     }
     68 
     69     @Implementation
     70     public void setContentView(int layoutResID) {
     71         layoutId = layoutResID;
     72     }
     73 
     74     @Implementation
     75     public void setContentView(View view) {
     76         inflatedView = view;
     77     }
     78 
     79     @Implementation
     80     public void setTitle(int stringResourceId) {
     81         this.title = context.getResources().getText(stringResourceId);
     82     }
     83 
     84     @Implementation(i18nSafe = false)
     85     public void setTitle(CharSequence title) {
     86         this.title = title;
     87     }
     88 
     89     @Implementation
     90     public void setOwnerActivity(Activity activity) {
     91         this.ownerActivity = activity;
     92     }
     93 
     94     @Implementation
     95     public Activity getOwnerActivity() {
     96         return this.ownerActivity;
     97     }
     98 
     99     @Implementation
    100     public Context getContext() {
    101         return context;
    102     }
    103 
    104     @Implementation
    105     public void onBackPressed() {
    106         cancel();
    107     }
    108 
    109     @Implementation
    110     public void show() {
    111         setLatestDialog(this);
    112         shownDialogs.add(realDialog);
    113         isShowing = true;
    114         try {
    115             if (!hasShownBefore) {
    116                 Method onCreateMethod = Dialog.class.getDeclaredMethod("onCreate", Bundle.class);
    117                 onCreateMethod.setAccessible(true);
    118                 onCreateMethod.invoke(realDialog, (Bundle) null);
    119             }
    120 
    121             Method onStartMethod = Dialog.class.getDeclaredMethod("onStart");
    122             onStartMethod.setAccessible(true);
    123             onStartMethod.invoke(realDialog);
    124         } catch (Exception e) {
    125             throw new RuntimeException(e);
    126         }
    127         hasShownBefore = true;
    128     }
    129 
    130     @Implementation
    131     public void hide() {
    132         isShowing = false;
    133     }
    134 
    135     @Implementation
    136     public boolean isShowing() {
    137         return isShowing;
    138     }
    139 
    140     @Implementation
    141     public void dismiss() {
    142         isShowing = false;
    143         hasBeenDismissed = true;
    144 
    145         if (onDismissListener != null) {
    146             onDismissListener.onDismiss(realDialog);
    147         }
    148     }
    149 
    150     @Implementation
    151     public View findViewById(int viewId) {
    152         if (inflatedView != null) {
    153             return inflatedView.findViewById(viewId);
    154         }
    155         if (layoutId > 0 && context != null) {
    156             inflatedView = ShadowLayoutInflater.from(context).inflate(layoutId, null);
    157             return inflatedView.findViewById(viewId);
    158         }
    159         return null;
    160     }
    161 
    162     public void clickOn(int viewId) {
    163         findViewById(viewId).performClick();
    164     }
    165 
    166     @Implementation
    167     public void setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
    168         this.onDismissListener = onDismissListener;
    169     }
    170 
    171     @Implementation
    172     public void setCancelable(boolean flag) {
    173         isCancelable = flag;
    174     }
    175 
    176     @Implementation
    177     public void setCanceledOnTouchOutside(boolean flag) {
    178         isCancelableOnTouchOutside = flag;
    179     }
    180 
    181     public boolean isCancelable() {
    182         return isCancelable;
    183     }
    184 
    185     public boolean isCancelableOnTouchOutside() {
    186         return isCancelableOnTouchOutside;
    187     }
    188 
    189     @Implementation
    190     public void cancel() {
    191         if (onCancelListener != null) {
    192             onCancelListener.onCancel(realDialog);
    193         }
    194         realDialog.dismiss();
    195     }
    196 
    197     @Implementation
    198     public void setOnCancelListener(DialogInterface.OnCancelListener listener) {
    199         this.onCancelListener = listener;
    200     }
    201 
    202     public DialogInterface.OnCancelListener getOnCancelListener() {
    203         return onCancelListener;
    204     }
    205 
    206     @Implementation
    207     public Window getWindow() {
    208         if (window == null) {
    209             window = new TestWindow(realDialog.getContext());
    210         }
    211         return window;
    212     }
    213 
    214 
    215     @Implementation
    216     public LayoutInflater getLayoutInflater() {
    217         return LayoutInflater.from(realDialog.getContext());
    218     }
    219 
    220     public int getLayoutId() {
    221         return layoutId;
    222     }
    223 
    224     public int getThemeId() {
    225         return themeId;
    226     }
    227 
    228     public boolean hasBeenDismissed() {
    229         return hasBeenDismissed;
    230     }
    231 
    232     public CharSequence getTitle() {
    233         return title;
    234     }
    235 
    236     public void clickOnText(int textId) {
    237         if (inflatedView == null) {
    238             inflatedView = ShadowLayoutInflater.from(context).inflate(layoutId, null);
    239         }
    240         String text = getContext().getResources().getString(textId);
    241         if (!clickOnText(inflatedView, text)) {
    242             throw new IllegalArgumentException("Text not found: " + text);
    243         }
    244     }
    245 
    246     private boolean clickOnText(View view, String text) {
    247         if (text.equals(shadowOf(view).innerText())) {
    248             view.performClick();
    249             return true;
    250         }
    251         if (view instanceof ViewGroup) {
    252             ViewGroup viewGroup = (ViewGroup) view;
    253             for (int i = 0; i < viewGroup.getChildCount(); i++) {
    254                 View child = viewGroup.getChildAt(i);
    255                 if (clickOnText(child, text)) {
    256                     return true;
    257                 }
    258             }
    259         }
    260         return false;
    261     }
    262 
    263     public static List<Dialog> getShownDialogs() {
    264         return shownDialogs;
    265     }
    266 }
    267