Flutter Engine
The Flutter Engine
StateAdapter.java
Go to the documentation of this file.
1package org.skia.viewer;
2
3import android.text.Editable;
4import android.text.TextWatcher;
5import android.view.LayoutInflater;
6import android.view.SurfaceView;
7import android.view.View;
8import android.view.ViewGroup;
9import android.widget.AdapterView;
10import android.widget.BaseAdapter;
11import android.widget.CompoundButton;
12import android.widget.EditText;
13import android.widget.LinearLayout;
14import android.widget.Spinner;
15import android.widget.Switch;
16import android.widget.TextView;
17
18import org.json.JSONArray;
19import org.json.JSONException;
20import org.json.JSONObject;
21
22import java.util.ArrayList;
23
24/*
25 The navigation drawer requires ListView, so we implemented this BaseAdapter for that ListView.
26 However, the ListView does not provide good support for updating just a single child view.
27 For example, a frequently changed child view such as FPS state will reset the spinner of
28 all other child views; although I didn't change other child views and directly return
29 the convertView in BaseAdapter.getView(int position, View convertView, ViewGroup parent).
30
31 Therefore, our adapter only returns one LinearLayout for the ListView.
32 Within that LinearLayout, we maintain views ourselves so we can efficiently update its children.
33 */
34public class StateAdapter extends BaseAdapter implements AdapterView.OnItemSelectedListener {
35 private static final String NAME = "name";
36 private static final String VALUE = "value";
37 private static final String OPTIONS = "options";
38 private static final String BACKEND_STATE_NAME = "Backend";
39 private static final String REFRESH_STATE_NAME = "Refresh";
40 private static final String ON = "ON";
41 private static final String OFF = "OFF";
42 private static final int FILTER_LENGTH = 20;
43
44 private ViewerActivity mViewerActivity;
45 private LinearLayout mLayout;
46 private JSONArray mStateJson;
47
48 public StateAdapter(ViewerActivity viewerActivity) {
49 mViewerActivity = viewerActivity;
50 try {
51 mStateJson = new JSONArray("[{\"name\": \"Please\", " +
52 "\"value\": \"Initialize\", \"options\": []}]");
53 } catch (JSONException e) {
54 e.printStackTrace();
55 }
56 }
57
58 public void setState(String stateJson) {
59 try {
60 mStateJson = new JSONArray(stateJson);
61 if (mLayout != null) {
62 updateDrawer();
63 } else {
64 notifyDataSetChanged();
65 }
66 } catch (JSONException e) {
67 e.printStackTrace();
68 }
69 }
70
71 // The first list item is the mLayout that contains a list of state items
72 @Override
73 public int getCount() {
74 return 1;
75 }
76
77 @Override
78 public Object getItem(int position) {
79 return null;
80 }
81
82 @Override
83 public long getItemId(int position) {
84 return 0;
85 }
86
87 @Override
88 public View getView(int position, View convertView, ViewGroup parent) {
89 switch (position) {
90 case 0: {
91 if (mLayout == null) {
92 mLayout = new LinearLayout(mViewerActivity);
93 mLayout.setOrientation(LinearLayout.VERTICAL);
94 updateDrawer();
95 }
96 return mLayout;
97 }
98 default: {
99 return null;
100 }
101 }
102 }
103
104 private void populateView(JSONObject item, View view) throws JSONException {
105 LinearLayout itemView = (LinearLayout) view;
106 TextView nameText = (TextView) itemView.findViewById(R.id.nameText);
107 TextView valueText = (TextView) itemView.findViewById(R.id.valueText);
108 Spinner optionSpinner = (Spinner) itemView.findViewById(R.id.optionSpinner);
109
110 String value = item.getString(VALUE);
111 itemView.setTag(item.toString()); // To save unnecessary view update
112 itemView.setTag(R.integer.value_tag_key, value);
113
114 nameText.setText(item.getString(NAME));
115
116 JSONArray options = item.getJSONArray(OPTIONS);
117 if (options.length() == 0) {
118 valueText.setText(value);
119 valueText.setVisibility(View.VISIBLE);
120 optionSpinner.setVisibility(View.GONE);
121 } else {
122 ArrayList<String> optionList = new ArrayList<>();
123 String[] optionStrings = new String[options.length()];
124 for (int j = 0; j < options.length(); j++) {
125 optionList.add(options.getString(j));
126 }
127 final OptionAdapter adapter = new OptionAdapter(mViewerActivity,
128 android.R.layout.simple_spinner_dropdown_item, optionList, optionSpinner);
129 adapter.setCurrentOption(value);
130 optionSpinner.setAdapter(adapter);
131 if (optionStrings.length >= FILTER_LENGTH) {
132 View existingView = itemView.getChildAt(1);
133 if (!(existingView instanceof EditText)) {
134 EditText filterText = new EditText(mViewerActivity);
135 filterText.setHint("Filter");
136 itemView.addView(filterText, 1);
137 filterText.addTextChangedListener(new TextWatcher() {
138 @Override
139 public void beforeTextChanged(CharSequence s, int start, int cnt,
140 int after) {
141 }
142
143 @Override
144 public void onTextChanged(CharSequence s, int start, int before, int cnt) {
145 }
146
147 @Override
148 public void afterTextChanged(Editable s) {
149 adapter.getFilter().filter(s.toString());
150 }
151 });
152 }
153 }
154 optionSpinner.setSelection(optionList.indexOf(value));
155 optionSpinner.setOnItemSelectedListener(this);
156 optionSpinner.setVisibility(View.VISIBLE);
157 valueText.setVisibility(View.GONE);
158 }
159 }
160 private View inflateItemView(JSONObject item) throws JSONException {
161 LinearLayout itemView = (LinearLayout)
162 LayoutInflater.from(mViewerActivity).inflate(R.layout.state_item, null);
163 populateView(item, itemView);
164 return itemView;
165 }
166
167 private void updateDrawer() {
168 try {
169 if (mStateJson.length() < mLayout.getChildCount()) {
170 mLayout.removeViews(
171 mStateJson.length(), mLayout.getChildCount() - mStateJson.length());
172 }
173 for (int i = 0; i < mStateJson.length(); i++) {
174 JSONObject stateObject = mStateJson.getJSONObject(i);
175 View childView = mLayout.getChildAt(i);
176 if (childView != null) {
177 if (stateObject.toString().equals(childView.getTag())) {
178 continue; // No update, reuse the old view and skip the remaining step
179 } else {
180 populateView(stateObject, childView);
181 }
182 } else {
183 mLayout.addView(inflateItemView(stateObject), i);
184 }
185 }
186 } catch (JSONException e) {
187 e.printStackTrace();
188 }
189 }
190
191 @Override
192 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
193 if (view == null) {
194 return;
195 }
196 View stateItem = (View) parent.getParent();
197 String stateName = ((TextView) stateItem.findViewById(R.id.nameText)).getText().toString();
198 String stateValue = ((TextView) view).getText().toString();
199 if (!stateValue.equals(stateItem.getTag(R.integer.value_tag_key))) {
200 stateItem.setTag(null); // Reset the tag to let updateDrawer update this item view.
201 mViewerActivity.onStateChanged(stateName, stateValue);
202 }
203
204 // Due to the current Android limitation, we're required to recreate the SurfaceView for
205 // switching to/from the Raster backend.
206 // (Although we can switch between GPU backend without recreating the SurfaceView.)
207 final Object oldValue = stateItem.getTag(R.integer.value_tag_key);
208 if (stateName.equals(BACKEND_STATE_NAME)
209 && oldValue != null && !stateValue.equals(oldValue)) {
210 LinearLayout mainLayout = (LinearLayout) mViewerActivity.findViewById(R.id.mainLayout);
211 mainLayout.removeAllViews();
212 SurfaceView surfaceView = new SurfaceView(mViewerActivity);
213 surfaceView.setId(R.id.surfaceView);
214 surfaceView.getHolder().addCallback(mViewerActivity);
215 surfaceView.setOnTouchListener(mViewerActivity);
216 mainLayout.addView(surfaceView);
217 }
218 }
219
220 @Override
221 public void onNothingSelected(AdapterView<?> parent) {
222 // do nothing
223 }
224}
const char * options
Object getItem(int position)
StateAdapter(ViewerActivity viewerActivity)
void setState(String stateJson)
View getView(int position, View convertView, ViewGroup parent)
long getItemId(int position)
void onItemSelected(AdapterView<?> parent, View view, int position, long id)
void onNothingSelected(AdapterView<?> parent)
void onStateChanged(String stateName, String stateValue)
struct MyStruct s
uint8_t value
#define R(r)