1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.documentsui;
17 
18 import static java.lang.annotation.ElementType.FIELD;
19 import static java.lang.annotation.RetentionPolicy.SOURCE;
20 
21 import android.support.annotation.Nullable;
22 import android.support.v7.widget.RecyclerView;
23 import android.view.MenuItem;
24 import android.view.View;
25 
26 import com.android.documentsui.MenuManager.SelectionDetails;
27 import com.android.documentsui.base.EventHandler;
28 import com.android.documentsui.base.Features;
29 import com.android.documentsui.dirlist.DocumentsAdapter;
30 import com.android.documentsui.base.DebugHelper;
31 import com.android.documentsui.prefs.ScopedPreferences;
32 import com.android.documentsui.queries.SearchViewManager;
33 import com.android.documentsui.selection.SelectionManager;
34 import com.android.documentsui.selection.SelectionManager.SelectionPredicate;
35 import com.android.documentsui.ui.DialogController;
36 import com.android.documentsui.ui.MessageBuilder;
37 import com.android.internal.annotations.VisibleForTesting;
38 
39 import java.lang.annotation.Retention;
40 import java.lang.annotation.Target;
41 
42 /**
43  * Provides access to runtime dependencies.
44  */
45 public class Injector<T extends ActionHandler> {
46 
47     public final Features features;
48     public final ActivityConfig config;
49     public final ScopedPreferences prefs;
50     public final MessageBuilder messages;
51 
52     public MenuManager menuManager;
53     public DialogController dialogs;
54     public SearchViewManager searchManager;
55 
56     @ContentScoped
57     public ActionModeController actionModeController;
58 
59     @ContentScoped
60     public T actions;
61 
62     @ContentScoped
63     public FocusManager focusManager;
64 
65     @ContentScoped
66     public SelectionManager selectionMgr;
67 
68     private final Model mModel;
69 
70     public final DebugHelper debugHelper;
71 
72     // must be initialized before calling super.onCreate because prefs
73     // are used in State initialization.
Injector( Features features, ActivityConfig config, ScopedPreferences prefs, MessageBuilder messages, DialogController dialogs)74     public Injector(
75             Features features,
76             ActivityConfig config,
77             ScopedPreferences prefs,
78             MessageBuilder messages,
79             DialogController dialogs) {
80         this(features, config, prefs, messages, dialogs, new Model(features));
81     }
82 
83     @VisibleForTesting
Injector( Features features, ActivityConfig config, ScopedPreferences prefs, MessageBuilder messages, DialogController dialogs, Model model)84     public Injector(
85             Features features,
86             ActivityConfig config,
87             ScopedPreferences prefs,
88             MessageBuilder messages,
89             DialogController dialogs,
90             Model model) {
91 
92         this.features = features;
93         this.config = config;
94         this.prefs = prefs;
95         this.messages = messages;
96         this.dialogs = dialogs;
97         this.mModel = model;
98         this.debugHelper = new DebugHelper(this);
99     }
100 
getModel()101     public Model getModel() {
102         return mModel;
103     }
104 
getFocusManager(RecyclerView view, Model model)105     public FocusManager getFocusManager(RecyclerView view, Model model) {
106         assert (focusManager != null);
107         return focusManager.reset(view, model);
108     }
109 
getSelectionManager( DocumentsAdapter adapter, SelectionPredicate canSetState)110     public SelectionManager getSelectionManager(
111             DocumentsAdapter adapter, SelectionPredicate canSetState) {
112         return selectionMgr.reset(adapter, canSetState);
113     }
114 
getActionModeController( SelectionDetails selectionDetails, EventHandler<MenuItem> menuItemClicker)115     public final ActionModeController getActionModeController(
116             SelectionDetails selectionDetails, EventHandler<MenuItem> menuItemClicker) {
117         return actionModeController.reset(selectionDetails, menuItemClicker);
118     }
119 
120     /**
121      * Obtains action handler and resets it if necessary.
122      * @param reloadLock the lock held by {@link com.android.documentsui.selection.BandController}
123      *                   to prevent loader from updating result during band selection. May be
124      *                   {@code null} if called from
125      *                   {@link com.android.documentsui.sidebar.RootsFragment}.
126      * @return the action handler
127      */
getActionHandler(@ullable DirectoryReloadLock reloadLock)128     public T getActionHandler(@Nullable DirectoryReloadLock reloadLock) {
129 
130         // provide our friend, RootsFragment, early access to this special feature!
131         if (reloadLock == null) {
132             return actions;
133         }
134 
135         return actions.reset(reloadLock);
136     }
137 
138     /**
139      * Decorates a field that that is injected.
140      */
141     @Retention(SOURCE)
142     @Target(FIELD)
143     public @interface Injected {
144 
145     }
146 
147     /**
148      * Decorates a field that holds an object that must be reset in the current content scope
149      * (i.e. DirectoryFragment). Fields decorated with this must have an associated
150      * accessor on Injector that, when call, reset the object for the calling context.
151      */
152     @Retention(SOURCE)
153     @Target(FIELD)
154     public @interface ContentScoped {
155 
156     }
157 }
158