xref: /aosp_15_r20/external/robolectric/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDialog.java (revision e6ba16074e6af37d123cb567d575f496bf0a58ee)
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