Home | History | Annotate | Download | only in ui
      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.facade.ui;
     18 
     19 import android.R;
     20 import android.os.Handler;
     21 import android.view.KeyEvent;
     22 import android.view.Menu;
     23 import android.view.View;
     24 import android.view.View.OnClickListener;
     25 import android.view.ViewGroup.LayoutParams;
     26 import android.widget.AdapterView;
     27 import android.widget.AdapterView.OnItemClickListener;
     28 import android.widget.Button;
     29 import android.widget.LinearLayout;
     30 import android.widget.TextView;
     31 
     32 import com.googlecode.android_scripting.facade.EventFacade;
     33 import com.googlecode.android_scripting.future.FutureActivityTask;
     34 
     35 import java.io.StringReader;
     36 import java.util.HashMap;
     37 import java.util.List;
     38 import java.util.Map;
     39 import java.util.concurrent.CountDownLatch;
     40 
     41 import org.json.JSONArray;
     42 import org.xmlpull.v1.XmlPullParser;
     43 
     44 public class FullScreenTask extends FutureActivityTask<Object> implements OnClickListener,
     45     OnItemClickListener {
     46   private EventFacade mEventFacade;
     47   private UiFacade mUiFacade;
     48   public View mView = null;
     49   protected ViewInflater mInflater = new ViewInflater();
     50   protected String mLayout;
     51   protected final CountDownLatch mShowLatch = new CountDownLatch(1);
     52   protected Handler mHandler = null;
     53   private List<Integer> mOverrideKeys;
     54   protected String mTitle;
     55 
     56   public FullScreenTask(String layout, String title) {
     57     super();
     58     mLayout = layout;
     59     if (title != null) {
     60       mTitle = title;
     61     } else {
     62       mTitle = "SL4a";
     63     }
     64   }
     65 
     66   @Override
     67   public void onCreate() {
     68     // super.onCreate();
     69     if (mHandler == null) {
     70       mHandler = new Handler();
     71     }
     72     mInflater.getErrors().clear();
     73     try {
     74       if (mView == null) {
     75         StringReader sr = new StringReader(mLayout);
     76         XmlPullParser xml = ViewInflater.getXml(sr);
     77         mView = mInflater.inflate(getActivity(), xml);
     78       }
     79     } catch (Exception e) {
     80       mInflater.getErrors().add(e.toString());
     81       mView = defaultView();
     82       mInflater.setIdList(R.id.class);
     83     }
     84     getActivity().setContentView(mView);
     85     getActivity().setTitle(mTitle);
     86     mInflater.setClickListener(mView, this, this);
     87     mShowLatch.countDown();
     88   }
     89 
     90   @Override
     91   public void onDestroy() {
     92     mEventFacade.postEvent("screen", "destroy");
     93     super.onDestroy();
     94   }
     95 
     96   /** default view in case of errors */
     97   protected View defaultView() {
     98     LinearLayout result = new LinearLayout(getActivity());
     99     result.setOrientation(LinearLayout.VERTICAL);
    100     TextView text = new TextView(getActivity());
    101     text.setText("Sample Layout");
    102     result.addView(text, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    103     Button b = new Button(getActivity());
    104     b.setText("OK");
    105     result.addView(b, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    106     return result;
    107   }
    108 
    109   public EventFacade getEventFacade() {
    110     return mEventFacade;
    111   }
    112 
    113   public void setEventFacade(EventFacade eventFacade) {
    114     mEventFacade = eventFacade;
    115   }
    116 
    117   public void setUiFacade(UiFacade uiFacade) {
    118     mUiFacade = uiFacade;
    119   }
    120 
    121   public CountDownLatch getShowLatch() {
    122     return mShowLatch;
    123   }
    124 
    125   public Map<String, Map<String, String>> getViewAsMap() {
    126     return mInflater.getViewAsMap(mView);
    127   }
    128 
    129   private View getViewByName(String idName) {
    130     View result = null;
    131     int id = mInflater.getId(idName);
    132     if (id != 0) {
    133       result = mView.findViewById(id);
    134     }
    135     return result;
    136   }
    137 
    138   public Map<String, String> getViewDetail(String idName) {
    139     Map<String, String> result = new HashMap<String, String>();
    140     result.put("error", "id not found (" + idName + ")");
    141     View v = getViewByName(idName);
    142     if (v != null) {
    143       result = mInflater.getViewInfo(v);
    144     }
    145     return result;
    146   }
    147 
    148   public String setViewProperty(String idName, String property, String value) {
    149     View v = getViewByName(idName);
    150     mInflater.getErrors().clear();
    151     if (v != null) {
    152       SetProperty p = new SetProperty(v, property, value);
    153       mHandler.post(p);
    154       try {
    155         p.mLatch.await();
    156       } catch (InterruptedException e) {
    157         mInflater.getErrors().add(e.toString());
    158       }
    159     } else {
    160       return "View " + idName + " not found.";
    161     }
    162     if (mInflater.getErrors().size() == 0) {
    163       return "OK";
    164     }
    165     return mInflater.getErrors().get(0);
    166   }
    167 
    168   public String setList(String id, JSONArray items) {
    169     View v = getViewByName(id);
    170     mInflater.getErrors().clear();
    171     if (v != null) {
    172       SetList p = new SetList(v, items);
    173       mHandler.post(p);
    174       try {
    175         p.mLatch.await();
    176       } catch (InterruptedException e) {
    177         mInflater.getErrors().add(e.toString());
    178       }
    179     } else {
    180       return "View " + id + " not found.";
    181     }
    182     if (mInflater.getErrors().size() == 0) {
    183       return "OK";
    184     }
    185     return mInflater.getErrors().get(0);
    186   }
    187 
    188   @Override
    189   public void onClick(View view) {
    190     mEventFacade.postEvent("click", mInflater.getViewInfo(view));
    191   }
    192 
    193   public void loadLayout(String layout) {
    194     ViewInflater inflater = new ViewInflater();
    195     View view;
    196     StringReader sr = new StringReader(layout);
    197     try {
    198       XmlPullParser xml = ViewInflater.getXml(sr);
    199       view = inflater.inflate(getActivity(), xml);
    200       mView = view;
    201       mInflater = inflater;
    202       getActivity().setContentView(mView);
    203       mInflater.setClickListener(mView, this, this);
    204       mLayout = layout;
    205       mView.invalidate();
    206     } catch (Exception e) {
    207       mInflater.getErrors().add(e.toString());
    208     }
    209   }
    210 
    211   private class SetProperty implements Runnable {
    212     View mView;
    213     String mProperty;
    214     String mValue;
    215     CountDownLatch mLatch = new CountDownLatch(1);
    216 
    217     SetProperty(View view, String property, String value) {
    218       mView = view;
    219       mProperty = property;
    220       mValue = value;
    221     }
    222 
    223     @Override
    224     public void run() {
    225       // TODO Auto-generated method stub
    226       mInflater.setProperty(mView, mProperty, mValue);
    227       mView.invalidate();
    228       mLatch.countDown();
    229     }
    230   }
    231 
    232   private class SetList implements Runnable {
    233     View mView;
    234     JSONArray mItems;
    235     CountDownLatch mLatch = new CountDownLatch(1);
    236 
    237     SetList(View view, JSONArray items) {
    238       mView = view;
    239       mItems = items;
    240       mLatch.countDown();
    241     }
    242 
    243     @Override
    244     public void run() {
    245       mInflater.setListAdapter(mView, mItems);
    246       mView.invalidate();
    247     }
    248   }
    249 
    250   private class SetLayout implements Runnable {
    251     String mLayout;
    252     CountDownLatch mLatch = new CountDownLatch(1);
    253 
    254     SetLayout(String layout) {
    255       mLayout = layout;
    256     }
    257 
    258     @Override
    259     public void run() {
    260       loadLayout(mLayout);
    261       mLatch.countDown();
    262     }
    263   }
    264 
    265   private class SetTitle implements Runnable {
    266     String mSetTitle;
    267     CountDownLatch mLatch = new CountDownLatch(1);
    268 
    269     SetTitle(String title) {
    270       mSetTitle = title;
    271     }
    272 
    273     @Override
    274     public void run() {
    275       mTitle = mSetTitle;
    276       getActivity().setTitle(mSetTitle);
    277       mLatch.countDown();
    278     }
    279   }
    280 
    281   @Override
    282   public boolean onKeyDown(int keyCode, KeyEvent event) {
    283     Map<String, String> data = new HashMap<String, String>();
    284     data.put("key", String.valueOf(keyCode));
    285     data.put("action", String.valueOf(event.getAction()));
    286     mEventFacade.postEvent("key", data);
    287     boolean overrideKey =
    288         (keyCode == KeyEvent.KEYCODE_BACK)
    289             || (mOverrideKeys == null ? false : mOverrideKeys.contains(keyCode));
    290     return overrideKey;
    291   }
    292 
    293   @Override
    294   public boolean onPrepareOptionsMenu(Menu menu) {
    295     return mUiFacade.onPrepareOptionsMenu(menu);
    296   }
    297 
    298   @Override
    299   public void onItemClick(AdapterView<?> aview, View aitem, int position, long id) {
    300     Map<String, String> data = mInflater.getViewInfo(aview);
    301     data.put("position", String.valueOf(position));
    302     mEventFacade.postEvent("itemclick", data);
    303   }
    304 
    305   public void setOverrideKeys(List<Integer> overrideKeys) {
    306     mOverrideKeys = overrideKeys;
    307   }
    308 
    309   // Used to hot-switch screens.
    310   public void setLayout(String layout) {
    311     SetLayout p = new SetLayout(layout);
    312     mHandler.post(p);
    313     try {
    314       p.mLatch.await();
    315     } catch (InterruptedException e) {
    316       mInflater.getErrors().add(e.toString());
    317     }
    318   }
    319 
    320   public void setTitle(String title) {
    321     SetTitle p = new SetTitle(title);
    322     mHandler.post(p);
    323     try {
    324       p.mLatch.await();
    325     } catch (InterruptedException e) {
    326       mInflater.getErrors().add(e.toString());
    327     }
    328   }
    329 
    330 }
    331