1 /* 2 * Copyright (C) 2017 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 17 package com.googlecode.android_scripting.activity; 18 19 import android.app.AlertDialog; 20 import android.app.ListActivity; 21 import android.content.DialogInterface; 22 import android.content.Intent; 23 import android.content.DialogInterface.OnClickListener; 24 import android.os.Bundle; 25 import android.view.ContextMenu; 26 import android.view.Menu; 27 import android.view.MenuItem; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.view.ContextMenu.ContextMenuInfo; 31 import android.widget.AdapterView; 32 import android.widget.BaseAdapter; 33 import android.widget.ListView; 34 import android.widget.TextView; 35 36 import com.google.common.collect.Lists; 37 import com.googlecode.android_scripting.ActivityFlinger; 38 import com.googlecode.android_scripting.BaseApplication; 39 import com.googlecode.android_scripting.Constants; 40 import com.googlecode.android_scripting.Log; 41 import com.googlecode.android_scripting.R; 42 import com.googlecode.android_scripting.facade.FacadeConfiguration; 43 import com.googlecode.android_scripting.rpc.MethodDescriptor; 44 import com.googlecode.android_scripting.trigger.ScriptTrigger; 45 import com.googlecode.android_scripting.trigger.Trigger; 46 import com.googlecode.android_scripting.trigger.TriggerRepository; 47 import com.googlecode.android_scripting.trigger.TriggerRepository.TriggerRepositoryObserver; 48 49 import java.io.File; 50 import java.util.Collections; 51 import java.util.List; 52 import java.util.Map; 53 54 public class TriggerManager extends ListActivity { 55 private final List<ScriptTrigger> mTriggers = Lists.newArrayList(); 56 57 private ScriptTriggerAdapter mAdapter; 58 private TriggerRepository mTriggerRepository; 59 60 private static enum ContextMenuId { 61 REMOVE; getId()62 public int getId() { 63 return ordinal() + Menu.FIRST; 64 } 65 } 66 67 private static enum MenuId { 68 ADD, PREFERENCES, HELP; getId()69 public int getId() { 70 return ordinal() + Menu.FIRST; 71 } 72 } 73 74 @Override onCreate(Bundle savedInstanceState)75 protected void onCreate(Bundle savedInstanceState) { 76 super.onCreate(savedInstanceState); 77 CustomizeWindow.requestCustomTitle(this, "Triggers", R.layout.trigger_manager); 78 ScriptTriggerListObserver observer = new ScriptTriggerListObserver(); 79 mAdapter = new ScriptTriggerAdapter(); 80 setListAdapter(mAdapter); 81 registerForContextMenu(getListView()); 82 mTriggerRepository = ((BaseApplication) getApplication()).getTriggerRepository(); 83 mTriggerRepository.bootstrapObserver(observer); 84 ActivityFlinger.attachView(getListView(), this); 85 ActivityFlinger.attachView(getWindow().getDecorView(), this); 86 } 87 88 @Override onCreateOptionsMenu(Menu menu)89 public boolean onCreateOptionsMenu(Menu menu) { 90 menu.add(Menu.NONE, MenuId.ADD.getId(), Menu.NONE, "Add").setIcon( 91 android.R.drawable.ic_menu_add); 92 menu.add(Menu.NONE, MenuId.PREFERENCES.getId(), Menu.NONE, "Preferences").setIcon( 93 android.R.drawable.ic_menu_preferences); 94 return true; 95 } 96 97 @Override onOptionsItemSelected(MenuItem item)98 public boolean onOptionsItemSelected(MenuItem item) { 99 int itemId = item.getItemId(); 100 if (itemId == MenuId.PREFERENCES.getId()) { 101 startActivity(new Intent(this, Preferences.class)); 102 } else if (itemId != Menu.NONE) { 103 Intent intent = new Intent(this, ScriptPicker.class); 104 intent.setAction(Intent.ACTION_PICK); 105 startActivityForResult(intent, itemId); 106 } 107 return true; 108 } 109 110 @Override onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)111 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 112 menu.add(Menu.NONE, ContextMenuId.REMOVE.getId(), Menu.NONE, "Remove"); 113 } 114 115 @Override onContextItemSelected(MenuItem item)116 public boolean onContextItemSelected(MenuItem item) { 117 AdapterView.AdapterContextMenuInfo info; 118 try { 119 info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); 120 } catch (ClassCastException e) { 121 Log.e("Bad menuInfo", e); 122 return false; 123 } 124 125 Trigger trigger = mAdapter.getItem(info.position); 126 if (trigger == null) { 127 Log.v("No trigger selected."); 128 return false; 129 } 130 131 if (item.getItemId() == ContextMenuId.REMOVE.getId()) { 132 mTriggerRepository.remove(trigger); 133 } 134 return true; 135 } 136 137 @Override onListItemClick(ListView l, View v, int position, long id)138 public void onListItemClick(ListView l, View v, int position, long id) { 139 mAdapter.notifyDataSetInvalidated(); 140 } 141 142 private class ScriptTriggerListObserver implements TriggerRepositoryObserver { 143 144 @Override onPut(Trigger trigger)145 public void onPut(Trigger trigger) { 146 mTriggers.add((ScriptTrigger) trigger); 147 mAdapter.notifyDataSetInvalidated(); 148 } 149 150 @Override onRemove(Trigger trigger)151 public void onRemove(Trigger trigger) { 152 mTriggers.remove(trigger); 153 mAdapter.notifyDataSetInvalidated(); 154 } 155 } 156 157 private class ScriptTriggerAdapter extends BaseAdapter { 158 159 @Override getCount()160 public int getCount() { 161 return mTriggers.size(); 162 } 163 164 @Override getItem(int position)165 public Trigger getItem(int position) { 166 return mTriggers.get(position); 167 } 168 169 @Override getItemId(int position)170 public long getItemId(int position) { 171 return position; 172 } 173 174 @Override getView(final int position, View convertView, ViewGroup parent)175 public View getView(final int position, View convertView, ViewGroup parent) { 176 ScriptTrigger trigger = mTriggers.get(position); 177 TextView textView = new TextView(TriggerManager.this); 178 textView.setText(trigger.getEventName() + " " + trigger.getScript().getName()); 179 return textView; 180 } 181 } 182 183 @Override onActivityResult(int requestCode, int resultCode, Intent data)184 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 185 if (resultCode == RESULT_OK) { 186 final File script = new File(data.getStringExtra(Constants.EXTRA_SCRIPT_PATH)); 187 if (requestCode == MenuId.ADD.getId()) { 188 Map<String, MethodDescriptor> eventMethodDescriptors = 189 FacadeConfiguration.collectStartEventMethodDescriptors(); 190 final List<String> eventNames = Lists.newArrayList(eventMethodDescriptors.keySet()); 191 Collections.sort(eventNames); 192 AlertDialog.Builder builder = new AlertDialog.Builder(this); 193 builder.setItems(eventNames.toArray(new CharSequence[eventNames.size()]), 194 new OnClickListener() { 195 @Override 196 public void onClick(DialogInterface dialog, int position) { 197 mTriggerRepository.put(new ScriptTrigger(eventNames.get(position), script)); 198 } 199 }); 200 builder.show(); 201 } 202 } 203 } 204 clickCancel(View v)205 public void clickCancel(View v) { 206 for (Trigger t : mTriggerRepository.getAllTriggers().values()) { 207 mTriggerRepository.remove(t); 208 } 209 } 210 } 211