1 package org.robolectric.shadows; 2 3 import static org.robolectric.util.reflector.Reflector.reflector; 4 5 import android.app.Activity; 6 import android.app.Dialog; 7 import android.content.Context; 8 import android.content.DialogInterface; 9 import android.os.Bundle; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.view.ViewGroup; 13 import android.view.Window; 14 import java.util.ArrayList; 15 import java.util.List; 16 import org.robolectric.annotation.Implementation; 17 import org.robolectric.annotation.Implements; 18 import org.robolectric.annotation.RealObject; 19 import org.robolectric.annotation.Resetter; 20 import org.robolectric.shadow.api.Shadow; 21 import org.robolectric.util.ReflectionHelpers; 22 import org.robolectric.util.ReflectionHelpers.ClassParameter; 23 import org.robolectric.util.reflector.Direct; 24 import org.robolectric.util.reflector.ForType; 25 26 @SuppressWarnings({"UnusedDeclaration"}) 27 @Implements(Dialog.class) 28 public class ShadowDialog { 29 30 @RealObject private Dialog realDialog; 31 32 private boolean isShowing; 33 Context context; 34 private int layoutId; 35 private int themeId; 36 private View inflatedView; 37 private boolean hasBeenDismissed; 38 protected CharSequence title; 39 private DialogInterface.OnCancelListener onCancelListener; 40 private Window window; 41 private Activity ownerActivity; 42 private boolean hasShownBefore; 43 private static final ArrayList<Dialog> shownDialogs = new ArrayList<>(); 44 private boolean isCancelableOnTouchOutside; 45 46 private static ShadowDialog latestDialog; 47 48 @Resetter reset()49 public static void reset() { 50 setLatestDialog(null); 51 shownDialogs.clear(); 52 } 53 getLatestDialog()54 public static Dialog getLatestDialog() { 55 return latestDialog == null ? null : latestDialog.realDialog; 56 } 57 setLatestDialog(ShadowDialog dialog)58 public static void setLatestDialog(ShadowDialog dialog) { 59 latestDialog = dialog; 60 } 61 62 @Implementation show()63 protected void show() { 64 setLatestDialog(this); 65 shownDialogs.add(realDialog); 66 reflector(DialogReflector.class, realDialog).show(); 67 } 68 69 @Implementation dismiss()70 protected void dismiss() { 71 reflector(DialogReflector.class, realDialog).dismiss(); 72 hasBeenDismissed = true; 73 } 74 clickOn(int viewId)75 public void clickOn(int viewId) { 76 realDialog.findViewById(viewId).performClick(); 77 } 78 79 @Implementation setCanceledOnTouchOutside(boolean flag)80 protected void setCanceledOnTouchOutside(boolean flag) { 81 isCancelableOnTouchOutside = flag; 82 reflector(DialogReflector.class, realDialog).setCanceledOnTouchOutside(flag); 83 } 84 isCancelable()85 public boolean isCancelable() { 86 return ReflectionHelpers.getField(realDialog, "mCancelable"); 87 } 88 isCancelableOnTouchOutside()89 public boolean isCancelableOnTouchOutside() { 90 return isCancelableOnTouchOutside; 91 } 92 getOnCancelListener()93 public DialogInterface.OnCancelListener getOnCancelListener() { 94 return onCancelListener; 95 } 96 97 @Implementation setOnCancelListener(DialogInterface.OnCancelListener listener)98 protected void setOnCancelListener(DialogInterface.OnCancelListener listener) { 99 this.onCancelListener = listener; 100 reflector(DialogReflector.class, realDialog).setOnCancelListener(listener); 101 } 102 hasBeenDismissed()103 public boolean hasBeenDismissed() { 104 return hasBeenDismissed; 105 } 106 getTitle()107 public CharSequence getTitle() { 108 ShadowWindow shadowWindow = Shadow.extract(realDialog.getWindow()); 109 return shadowWindow.getTitle(); 110 } 111 clickOnText(int textId)112 public void clickOnText(int textId) { 113 if (inflatedView == null) { 114 inflatedView = LayoutInflater.from(context).inflate(layoutId, null); 115 } 116 String text = realDialog.getContext().getResources().getString(textId); 117 if (!clickOnText(inflatedView, text)) { 118 throw new IllegalArgumentException("Text not found: " + text); 119 } 120 } 121 clickOnText(String text)122 public void clickOnText(String text) { 123 if (!clickOnText(inflatedView, text)) { 124 throw new IllegalArgumentException("Text not found: " + text); 125 } 126 } 127 clickOnText(View view, String text)128 private boolean clickOnText(View view, String text) { 129 ShadowView shadowView = Shadow.extract(view); 130 if (text.equals(shadowView.innerText())) { 131 view.performClick(); 132 return true; 133 } 134 if (view instanceof ViewGroup) { 135 ViewGroup viewGroup = (ViewGroup) view; 136 for (int i = 0; i < viewGroup.getChildCount(); i++) { 137 View child = viewGroup.getChildAt(i); 138 if (clickOnText(child, text)) { 139 return true; 140 } 141 } 142 } 143 return false; 144 } 145 getShownDialogs()146 public static List<Dialog> getShownDialogs() { 147 return shownDialogs; 148 } 149 callOnCreate(Bundle bundle)150 public void callOnCreate(Bundle bundle) { 151 ReflectionHelpers.callInstanceMethod( 152 realDialog, "onCreate", ClassParameter.from(Bundle.class, bundle)); 153 } 154 155 @ForType(Dialog.class) 156 interface DialogReflector { 157 158 @Direct show()159 void show(); 160 161 @Direct dismiss()162 void dismiss(); 163 164 @Direct setCanceledOnTouchOutside(boolean flag)165 void setCanceledOnTouchOutside(boolean flag); 166 167 @Direct setOnCancelListener(DialogInterface.OnCancelListener listener)168 void setOnCancelListener(DialogInterface.OnCancelListener listener); 169 } 170 } 171