EMMA Coverage Report (generated Wed Jun 27 17:43:42 CEST 2012)
[all classes][aarddict.android]

COVERAGE SUMMARY FOR SOURCE FILE [LookupActivity.java]

nameclass, %method, %block, %line, %
LookupActivity.java77%  (10/13)82%  (45/55)79%  (816/1039)79%  (166,8/211)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LookupActivity$50%   (0/1)0%   (0/2)0%   (0/31)0%   (0/4)
LookupActivity$5 (LookupActivity, String): void 0%   (0/1)0%   (0/9)0%   (0/1)
run (): void 0%   (0/1)0%   (0/22)0%   (0/3)
     
class LookupActivity$WordAdapter$10%   (0/1)0%   (0/2)0%   (0/18)0%   (0/4)
LookupActivity$WordAdapter$1 (LookupActivity$WordAdapter): void 0%   (0/1)0%   (0/6)0%   (0/1)
run (): void 0%   (0/1)0%   (0/12)0%   (0/3)
     
class LookupActivity$WordAdapter$1$10%   (0/1)0%   (0/2)0%   (0/11)0%   (0/3)
LookupActivity$WordAdapter$1$1 (LookupActivity$WordAdapter$1): void 0%   (0/1)0%   (0/6)0%   (0/1)
run (): void 0%   (0/1)0%   (0/5)0%   (0/2)
     
class LookupActivity$3100% (1/1)50%  (1/2)29%  (6/21)25%  (1/4)
onClick (View): void 0%   (0/1)0%   (0/15)0%   (0/3)
LookupActivity$3 (LookupActivity): void 100% (1/1)100% (6/6)100% (1/1)
     
class LookupActivity$7100% (1/1)100% (2/2)47%  (14/30)50%  (3/6)
onKey (View, int, KeyEvent): boolean 100% (1/1)33%  (8/24)40%  (2/5)
LookupActivity$7 (LookupActivity): void 100% (1/1)100% (6/6)100% (1/1)
     
class LookupActivity$WordAdapter100% (1/1)73%  (8/11)79%  (128/163)76%  (29/38)
access$200 (LookupActivity$WordAdapter): void 0%   (0/1)0%   (0/3)0%   (0/1)
getItem (int): Object 0%   (0/1)0%   (0/3)0%   (0/1)
loadMore (int): void 0%   (0/1)0%   (0/17)0%   (0/5)
createView (ViewGroup): TwoLineListItem 100% (1/1)68%  (19/28)83%  (5/6)
getView (int, View, ViewGroup): View 100% (1/1)90%  (28/31)80%  (4/5)
LookupActivity$WordAdapter (LookupActivity, Iterator): void 100% (1/1)100% (22/22)100% (6/6)
bindView (TwoLineListItem, Entry): void 100% (1/1)100% (15/15)100% (3/3)
getCount (): int 100% (1/1)100% (3/3)100% (1/1)
getItemId (int): long 100% (1/1)100% (3/3)100% (1/1)
loadBatch (): void 100% (1/1)100% (29/29)100% (7/7)
onItemClick (AdapterView, View, int, long): void 100% (1/1)100% (9/9)100% (2/2)
     
class LookupActivity$6100% (1/1)100% (4/4)85%  (33/39)83%  (10/12)
afterTextChanged (Editable): void 100% (1/1)81%  (25/31)78%  (7/9)
LookupActivity$6 (LookupActivity): void 100% (1/1)100% (6/6)100% (1/1)
beforeTextChanged (CharSequence, int, int, int): void 100% (1/1)100% (1/1)100% (1/1)
onTextChanged (CharSequence, int, int, int): void 100% (1/1)100% (1/1)100% (1/1)
     
class LookupActivity$1100% (1/1)100% (2/2)85%  (61/72)87%  (13/15)
run (): void 100% (1/1)83%  (52/63)86%  (12/14)
LookupActivity$1 (LookupActivity, Iterator): void 100% (1/1)100% (9/9)100% (1/1)
     
class LookupActivity100% (1/1)100% (20/20)86%  (483/563)85%  (102/120)
onDictionaryServiceReady (): void 100% (1/1)47%  (22/47)42%  (5/12)
doLookup (CharSequence): void 100% (1/1)63%  (53/84)65%  (13/20)
initUI (): void 100% (1/1)86%  (61/71)87%  (13/15)
showAbout (): void 100% (1/1)92%  (172/186)95%  (35/37)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
LookupActivity (): void 100% (1/1)100% (15/15)100% (4/4)
access$000 (LookupActivity): EditText 100% (1/1)100% (3/3)100% (1/1)
access$100 (LookupActivity): ListView 100% (1/1)100% (3/3)100% (1/1)
access$300 (LookupActivity, Entry): void 100% (1/1)100% (4/4)100% (1/1)
access$400 (): String 100% (1/1)100% (2/2)100% (1/1)
access$500 (LookupActivity, CharSequence): void 100% (1/1)100% (4/4)100% (1/1)
access$600 (LookupActivity): Timer 100% (1/1)100% (3/3)100% (1/1)
launchWord (Entry): void 100% (1/1)100% (37/37)100% (8/8)
onCreateOptionsMenu (Menu): boolean 100% (1/1)100% (20/20)100% (3/3)
onDestroy (): void 100% (1/1)100% (6/6)100% (3/3)
onDictionaryOpenFinished (): void 100% (1/1)100% (3/3)100% (2/2)
onOptionsItemSelected (MenuItem): boolean 100% (1/1)100% (15/15)100% (5/5)
trimLeft (String): String 100% (1/1)100% (5/5)100% (1/1)
updateTitle (): void 100% (1/1)100% (43/43)100% (7/7)
updateWordListUI (Iterator): void 100% (1/1)100% (8/8)100% (2/2)
     
class LookupActivity$2100% (1/1)100% (2/2)100% (11/11)100% (3/3)
LookupActivity$2 (LookupActivity): void 100% (1/1)100% (6/6)100% (1/1)
run (): void 100% (1/1)100% (5/5)100% (2/2)
     
class LookupActivity$4100% (1/1)100% (2/2)100% (9/9)100% (3/3)
LookupActivity$4 (LookupActivity): void 100% (1/1)100% (6/6)100% (1/1)
onClick (DialogInterface, int): void 100% (1/1)100% (3/3)100% (2/2)
     
class LookupActivity$6$1100% (1/1)100% (2/2)100% (41/41)100% (5/5)
LookupActivity$6$1 (LookupActivity$6, Editable): void 100% (1/1)100% (9/9)100% (1/1)
run (): void 100% (1/1)100% (32/32)100% (4/4)
     
class LookupActivity$8100% (1/1)100% (2/2)100% (30/30)100% (6/6)
LookupActivity$8 (LookupActivity): void 100% (1/1)100% (6/6)100% (1/1)
onClick (View): void 100% (1/1)100% (24/24)100% (5/5)

1/* This file is part of Aard Dictionary for Android <http://aarddict.org>.
2 * 
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 3
5 * as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License <http://www.gnu.org/licenses/gpl-3.0.txt>
11 * for more details.
12 * 
13 * Copyright (C) 2010 Igor Tkach
14*/
15 
16package aarddict.android;
17 
18import java.util.ArrayList;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Timer;
22import java.util.TimerTask;
23 
24import aarddict.Entry;
25import android.app.AlertDialog;
26import android.content.Context;
27import android.content.DialogInterface;
28import android.content.Intent;
29import android.content.DialogInterface.OnClickListener;
30import android.content.pm.PackageInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
33import android.content.res.Resources;
34import android.net.Uri;
35import android.text.Editable;
36import android.text.Html;
37import android.text.InputType;
38import android.text.TextUtils;
39import android.text.TextWatcher;
40import android.text.method.LinkMovementMethod;
41import android.util.Log;
42import android.view.Gravity;
43import android.view.KeyEvent;
44import android.view.LayoutInflater;
45import android.view.Menu;
46import android.view.MenuItem;
47import android.view.View;
48import android.view.View.OnKeyListener;
49import android.view.ViewGroup;
50import android.view.Window;
51import android.view.inputmethod.InputMethodManager;
52import android.widget.AdapterView;
53import android.widget.BaseAdapter;
54import android.widget.Button;
55import android.widget.EditText;
56import android.widget.ImageButton;
57import android.widget.ImageView;
58import android.widget.LinearLayout;
59import android.widget.ListView;
60import android.widget.TextView;
61import android.widget.TwoLineListItem;
62 
63public class LookupActivity extends BaseDictionaryActivity {
64    
65    private final static String TAG     = LookupActivity.class.getName();
66    
67    private Timer                  timer;
68    private ListView               listView;
69    private Iterator<Entry> empty = new ArrayList<Entry>().iterator();
70    
71    void updateTitle() {
72            int dictCount = dictionaryService.getVolumes().size();
73            Resources r = getResources();
74                String dictionaries = r.getQuantityString(R.plurals.dictionaries, dictCount);
75            String appName = r.getString(R.string.appName);
76            String mainTitle = r.getString(R.string.titleLookupActivity, appName, String.format(dictionaries, dictCount));
77            setTitle(mainTitle);            
78    }
79    
80    @Override
81    protected void onDestroy() {
82        super.onDestroy();
83        timer.cancel();
84    }
85        
86    private void updateWordListUI(final Iterator<Entry> results) {        
87        runOnUiThread(new Runnable() {
88            public void run() {
89                TextView messageView = (TextView)findViewById(R.id.messageView);
90                if (!results.hasNext()) {                        
91                    Editable text = editText.getText();
92                    if (text != null && !text.toString().equals("")) {                            
93                            messageView.setText(Html.fromHtml(getString(R.string.nothingFound)));
94                            messageView.setVisibility(View.VISIBLE);
95                    }
96                    else {
97                            messageView.setVisibility(View.GONE);
98                    }
99                }
100                else {
101                        messageView.setVisibility(View.GONE);
102                }
103                WordAdapter wordAdapter = new WordAdapter(results);
104                listView.setAdapter(wordAdapter);        
105                listView.setOnItemClickListener(wordAdapter);                
106                setProgressBarIndeterminateVisibility(false);
107            }
108        });                
109    }    
110 
111    final Runnable updateProgress = new Runnable() {
112        public void run() {
113            setProgressBarIndeterminateVisibility(true);
114        }
115    };        
116    
117    private void doLookup(CharSequence word) {
118        if (dictionaryService == null)
119            return;
120        word = trimLeft(word.toString());
121        if (word.equals("")) {
122                Log.d(TAG, "Nothing to look up");
123                updateWordListUI(empty);
124                return;
125        }
126        runOnUiThread(updateProgress);
127        long t0 = System.currentTimeMillis();
128        try {
129            Iterator<Entry> results = dictionaryService.lookup(word);
130            Log.d(TAG, "Looked up " + word + " in "
131                    + (System.currentTimeMillis() - t0));
132            updateWordListUI(results);
133        } catch (Exception e) {
134            StringBuilder msgBuilder = new StringBuilder(
135                    "There was an error while looking up ").append("\"")
136                    .append(word).append("\"");
137            if (e.getMessage() != null) {
138                msgBuilder.append(": ").append(e.getMessage());
139            }
140            final String msg = msgBuilder.toString();
141            Log.e(TAG, msg, e);
142        }
143    }
144    
145    private void launchWord(Entry theWord) {
146        Intent next = new Intent();
147        next.setClass(this, ArticleViewActivity.class);
148        next.putExtra("word", theWord.title);        
149        next.putExtra("section", theWord.section);
150        next.putExtra("volumeId", theWord.volumeId);
151        next.putExtra("articlePointer", theWord.articlePointer);
152        startActivity(next);
153    }
154 
155    
156    final class WordAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
157 
158        private final List<Entry>    words;
159        private final LayoutInflater mInflater;
160        private int                  itemCount;
161        private Iterator<Entry>      results;
162        private boolean              displayMore;
163 
164        public WordAdapter(Iterator<Entry> results) {
165            this.results = results;                        
166            this.words = new ArrayList<Entry>();                        
167            loadBatch();
168            mInflater = (LayoutInflater) LookupActivity.this.getSystemService(
169                    Context.LAYOUT_INFLATER_SERVICE);
170        }
171 
172        private void loadBatch() {
173            int count = 0;                
174            while (results.hasNext() && count < 20) {
175                count++;
176                words.add(results.next());
177            }                                        
178            displayMore = results.hasNext();
179            itemCount = words.size();              
180        }
181        
182        public int getCount() {
183            return itemCount;
184        }
185 
186        public Object getItem(int position) {
187            return position;
188        }
189 
190        public long getItemId(int position) {
191            return position;
192        }
193        
194        public View getView(int position, View convertView, ViewGroup parent) {
195            if (displayMore && position == itemCount - 1) {
196                    loadMore(position);
197            }            
198            TwoLineListItem view = (convertView != null) ? (TwoLineListItem) convertView :
199                    createView(parent);            
200            bindView(view, words.get(position));
201            return view;
202        }
203        
204        private int loadingMoreForPos;
205 
206        private void loadMore(int forPos) {
207                if (loadingMoreForPos == forPos) {
208                        return;
209                }
210                loadingMoreForPos = forPos;
211                new Thread(new Runnable() {                                
212                        public void run() {
213                                loadBatch();
214                                runOnUiThread(new Runnable() {                                                
215                                        public void run() {
216                                                notifyDataSetChanged();
217                                        }
218                                });
219                        }
220                }).start();                                
221        }        
222        
223        private TwoLineListItem createView(ViewGroup parent) {
224                TwoLineListItem item;
225                if (DeviceInfo.EINK_SCREEN)
226                        item = (TwoLineListItem) mInflater.inflate(
227                        R.layout.eink_simple_list_item_2, parent, false);
228                else
229                item = (TwoLineListItem) mInflater.inflate(
230                        android.R.layout.simple_list_item_2, parent, false);
231            item.getText2().setSingleLine();
232            item.getText2().setEllipsize(TextUtils.TruncateAt.END);
233            return item;
234        }
235 
236        private void bindView(TwoLineListItem view, Entry word) {
237            view.getText1().setText(word.title);
238            view.getText2().setText(dictionaryService.getDisplayTitle(word.volumeId));
239        }
240 
241        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
242                launchWord(words.get(position));
243        }
244    }
245        
246    
247    final static int MENU_DICT_INFO = 1;
248    final static int MENU_ABOUT = 2;
249    final static int MENU_DICT_REFRESH = 3;    
250    private EditText editText;
251 
252    private TextWatcher textWatcher;
253    
254    @Override
255    public boolean onCreateOptionsMenu(Menu menu) {
256        menu.add(0, MENU_DICT_INFO, 0, R.string.mnInfo).setIcon(android.R.drawable.ic_menu_info_details);
257        menu.add(0, MENU_ABOUT, 0, R.string.mnAbout).setIcon(R.drawable.ic_menu_aarddict);
258        return true;
259    }
260    
261    @Override
262    public boolean onOptionsItemSelected(MenuItem item) {
263        switch (item.getItemId()) {
264        case MENU_DICT_INFO:
265            startActivity(new Intent(this, DictionariesActivity.class));                
266            break;
267        case MENU_ABOUT:
268            showAbout();
269            break;            
270        }
271        return true;
272    }
273 
274        private void showAbout() {        
275        PackageManager manager = getPackageManager();
276        String versionName = "";
277        try {
278                        PackageInfo info = manager.getPackageInfo(getPackageName(), 0);
279                        versionName = info.versionName;
280                } catch (NameNotFoundException e) {
281                        Log.e(TAG, "Failed to load package info for " + getPackageName(), e) ;
282                }        
283                
284        LinearLayout layout = new LinearLayout(this);
285        layout.setOrientation(LinearLayout.HORIZONTAL);
286        layout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, 
287                    LinearLayout.LayoutParams.FILL_PARENT, 1));
288        layout.setPadding(10, 10, 10, 10);
289        ImageView logo = new ImageView(this);
290        logo.setImageResource(R.drawable.aarddict);
291        logo.setPadding(0, 0, 20, 0);
292        logo.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.FILL_PARENT));
293        TextView textView = new TextView(this);
294        textView.setGravity(Gravity.CENTER_HORIZONTAL);
295        textView.setLineSpacing(2f, 1);
296        textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.FILL_PARENT));
297        textView.setMovementMethod(LinkMovementMethod.getInstance());
298        textView.setText(Html.fromHtml(getString(R.string.about, getString(R.string.appName), versionName)));
299 
300        ImageView btnFlattr = new ImageView(this);
301        btnFlattr.setImageResource(R.drawable.flattr);
302        btnFlattr.setPadding(5, 5, 5, 5);
303        btnFlattr.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 
304                                                                                                        ViewGroup.LayoutParams.WRAP_CONTENT));
305        btnFlattr.setOnClickListener(new View.OnClickListener() {                        
306                        public void onClick(View v) {
307                Intent browserIntent = new Intent(Intent.ACTION_VIEW, 
308                        Uri.parse(getString(R.string.flattrUrl))); 
309                startActivity(browserIntent);
310                        }
311                });
312        
313        LinearLayout textViewLayout = new LinearLayout(this);
314        textViewLayout.setOrientation(LinearLayout.VERTICAL);
315        textViewLayout.setPadding(0, 0, 0, 10);
316        textViewLayout.addView(textView);      
317        textViewLayout.addView(btnFlattr);
318        
319        layout.addView(logo);
320        layout.addView(textViewLayout);
321        
322                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
323        dialogBuilder.setTitle(R.string.titleAbout).setView(layout).setNeutralButton(R.string.btnDismiss, new OnClickListener() {            
324            public void onClick(DialogInterface dialog, int which) {
325                dialog.dismiss();
326            }
327        });
328        dialogBuilder.show();
329        }
330        
331    @Override
332    void onDictionaryServiceReady() {            
333            updateTitle();
334            Intent intent = getIntent();
335        if (intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_SEARCH)) {
336            final String word = intent.getStringExtra("query");
337            editText.setText(word);
338 
339            try {
340                timer.schedule(new TimerTask() {
341                    @Override
342                    public void run() {
343                        Log.d(TAG, "running lookup task for " + word + " in " + Thread.currentThread());
344                        doLookup(word);
345                    }
346                }, 0);
347            }
348            catch(IllegalStateException e) {
349                Log.e(TAG, "Failed to schedule lookup task", e);
350            }
351        }
352        else {            
353            textWatcher.afterTextChanged(editText.getText());
354        }
355    }
356    
357    @Override
358    void onDictionaryOpenFinished() {
359            onDictionaryServiceReady();
360    }
361        
362    @Override
363    void initUI() {
364        getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
365        
366        if (DeviceInfo.EINK_SCREEN)
367        {
368                setContentView(R.layout.eink_lookup);
369            listView = (ListView)findViewById(R.id.einkLookupResult);
370        }
371        else
372        {
373                setContentView(R.layout.lookup);
374            listView = (ListView)findViewById(R.id.lookupResult);
375        }
376        
377        timer = new Timer();
378                                                             
379        editText = (EditText)findViewById(R.id.wordInput);
380                        
381        textWatcher = new TextWatcher() {
382            
383            TimerTask currentLookupTask;
384            
385            public void onTextChanged(CharSequence s, int start, int before, int count) {
386            }
387            
388            public void beforeTextChanged(CharSequence s, int start, int count,
389                    int after) {
390            }
391            
392            public void afterTextChanged(Editable s) {
393                if (currentLookupTask != null) {
394                    currentLookupTask.cancel();
395                }                                        
396                                
397                final Editable textToLookup = s;                 
398                currentLookupTask = new TimerTask() {                    
399                    @Override
400                    public void run() {
401                        Log.d(TAG, "running lookup task for " + textToLookup + " in " + Thread.currentThread());
402                        if (textToLookup.equals(editText.getText())) {
403                            doLookup(textToLookup);
404                        }
405                    }
406                };
407                try {
408                        timer.schedule(currentLookupTask, 600);                        
409                }
410                catch(IllegalStateException e) {
411                        //this may happen if orientation changes while loading                        
412                        Log.d(TAG, "Failed to schedule lookup task", e);
413                }
414            }
415        };
416        editText.addTextChangedListener(textWatcher);
417        
418        editText.setOnKeyListener(new OnKeyListener() {
419            public boolean onKey(View v, int keyCode, KeyEvent event) {
420                     if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
421                             InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
422                             inputManager.hideSoftInputFromWindow(editText.getApplicationWindowToken(), 0);
423                             return true;
424                     }
425                     return false;
426            }
427        });        
428 
429        editText.setInputType(InputType.TYPE_CLASS_TEXT);
430                
431        Button btnClear = (Button)findViewById(R.id.clearButton);
432        btnClear.setOnClickListener(new View.OnClickListener() {
433            public void onClick(View v) {
434                editText.setText("");
435                editText.requestFocus();
436                InputMethodManager inputMgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
437                inputMgr.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
438            }
439        });  
440        
441    }
442    
443    static String trimLeft(String s) {
444        return s.replaceAll("^\\s+", "");
445    }
446}

[all classes][aarddict.android]
EMMA 0.0.0 (unsupported private build) (C) Vladimir Roubtsov