1 /***
2 * Aedict - an EDICT browser for Android
3 Copyright (C) 2009 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 package sk.baka.aedict;
19
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24
25 import sk.baka.aedict.dict.DictEntry;
26 import sk.baka.aedict.dict.DictTypeEnum;
27 import sk.baka.aedict.dict.Dictionary;
28 import sk.baka.aedict.dict.EdictEntry;
29 import sk.baka.aedict.dict.LuceneSearch;
30 import sk.baka.aedict.dict.MatcherEnum;
31 import sk.baka.aedict.dict.SearchQuery;
32 import sk.baka.aedict.dict.TanakaDictEntry;
33 import sk.baka.aedict.util.DictEntryListActions;
34 import sk.baka.aedict.util.ShowRomaji;
35 import sk.baka.autils.AbstractTask;
36 import sk.baka.autils.MiscUtils;
37 import sk.baka.autils.Progress;
38 import android.app.Activity;
39 import android.app.ListActivity;
40 import android.content.Intent;
41 import android.os.Bundle;
42 import android.view.Menu;
43 import android.view.View;
44 import android.view.ViewGroup;
45 import android.widget.ArrayAdapter;
46 import android.widget.ListView;
47 import android.widget.TextView;
48
49 /***
50 * Perform analysis of the Tanaka sentence.
51 *
52 * @author Martin Vysny
53 */
54 public class TanakaAnalyzeActivity extends ListActivity {
55 /***
56 * The {@link TanakaDictEntry} to analyze.
57 */
58 static final String INTENTKEY_TANAKADICTENTRY = "tanakaDictEntry";
59 private static final String INTENTKEY_STATE = "state";
60
61 public static void launch(final Activity activity, final TanakaDictEntry td) {
62 if (td == null || td.wordList == null || td.wordList.isEmpty()) {
63 throw new IllegalArgumentException("word is null");
64 }
65 if (!AedictApp.getDownloader().checkDictionary(activity, new Dictionary(DictTypeEnum.Tanaka, null), null, false)) {
66 return;
67 }
68 final Intent i = new Intent(activity, TanakaAnalyzeActivity.class);
69 i.putExtra(INTENTKEY_TANAKADICTENTRY, td);
70 activity.startActivity(i);
71 }
72
73 private ShowRomaji showRomaji;
74 private List<DictEntry> model = null;
75 private TanakaDictEntry tanaka;
76
77 @SuppressWarnings("unchecked")
78 @Override
79 protected void onRestoreInstanceState(Bundle savedInstanceState) {
80 model = (List<DictEntry>) savedInstanceState.getSerializable(INTENTKEY_STATE);
81 showRomaji.loadState(savedInstanceState);
82 setListAdapter(newAdapter());
83 }
84
85 private ArrayAdapter<DictEntry> newAdapter() {
86 return new ArrayAdapter<DictEntry>(this, R.layout.kanjidic_list_item, model) {
87
88 @Override
89 public View getView(int position, View convertView, ViewGroup parent) {
90 View v = convertView;
91 if (v == null) {
92 v = getLayoutInflater().inflate(R.layout.kanjidic_list_item, getListView(), false);
93 }
94 final DictEntry e = model.get(position);
95 ((TextView) v.findViewById(android.R.id.text1)).setText(showRomaji.romanize(e.reading));
96 final StringBuilder sb = new StringBuilder();
97 sb.insert(0, e.english);
98 ((TextView) v.findViewById(android.R.id.text2)).setText(sb.toString());
99 final TextView tv = (TextView) v.findViewById(R.id.kanjiBig);
100
101
102
103 tv.setText(splitToRows(e.getJapanese()));
104 return v;
105 }
106
107 private String splitToRows(final String str) {
108 if (str == null) {
109 return "";
110 }
111 final StringBuilder sb = new StringBuilder(str.length() * 4 / 3);
112 for (int i = 0; i < str.length(); i++) {
113 if ((i > 0) && (i % 3 == 0)) {
114 sb.append('\n');
115 }
116 sb.append(str.charAt(i));
117 }
118 return sb.toString();
119 }
120 };
121 }
122
123 @Override
124 protected void onSaveInstanceState(Bundle outState) {
125 showRomaji.saveState(outState);
126 outState.putSerializable(INTENTKEY_STATE, (Serializable) model);
127 }
128
129 @Override
130 protected void onListItemClick(ListView l, View v, int position, long id) {
131 final DictEntry e = model.get(position);
132 if (!e.isValid()) {
133 return;
134 }
135 if (e instanceof EdictEntry) {
136 EdictEntryDetailActivity.launch(this, (EdictEntry) e);
137 }
138 }
139
140 @Override
141 protected void onCreate(Bundle savedInstanceState) {
142 super.onCreate(savedInstanceState);
143 showRomaji = new ShowRomaji() {
144
145 @Override
146 protected void show(boolean romaji) {
147 if (getListAdapter() != null) {
148 ((ArrayAdapter<?>) getListAdapter()).notifyDataSetChanged();
149 }
150 }
151 };
152 tanaka = (TanakaDictEntry) getIntent().getSerializableExtra(INTENTKEY_TANAKADICTENTRY);
153 new DictEntryListActions(this, true, true, false, true).register(getListView());
154 }
155
156 @Override
157 protected void onResume() {
158 super.onResume();
159 showRomaji.onResume();
160 if(model==null){
161 recomputeModel();
162 }
163 }
164
165 @Override
166 public boolean onPrepareOptionsMenu(Menu menu) {
167 menu.clear();
168 showRomaji.register(this, menu);
169 return true;
170 }
171
172 private void recomputeModel() {
173 new RecomputeModel().execute(AedictApp.isInstrumentation, this, tanaka);
174 }
175
176 private class RecomputeModel extends AbstractTask<TanakaDictEntry, List<DictEntry>> {
177
178 @Override
179 protected void cleanupAfterError(Exception ex) {
180
181 }
182
183 @Override
184 protected void onSucceeded(List<DictEntry> result) {
185 model = result;
186 model.add(0, new DictEntry("", tanaka.kanji + "\n" + tanaka.reading, tanaka.english));
187 setListAdapter(newAdapter());
188 }
189
190 @Override
191 public List<DictEntry> impl(TanakaDictEntry... params) throws Exception {
192 publish(new Progress(AedictApp.getStr(R.string.analyzing), 0, 100));
193 final List<DictEntry> result = new ArrayList<DictEntry>();
194 final LuceneSearch lsEdict = new LuceneSearch(DictTypeEnum.Edict, AedictApp.getConfig().getDictionaryLoc(), true);
195 try {
196 final TanakaDictEntry e = params[0];
197 for (int i = 0; i < e.wordList.size(); i++) {
198 publish(new Progress(null, i, e.wordList.size()));
199 if (isCancelled()) {
200 return null;
201 }
202 final String kanji = e.wordList.get(i);
203 final SearchQuery q = SearchQuery.searchJpEdict(kanji, MatcherEnum.Exact);
204 final List<DictEntry> matches = lsEdict.search(q, 10);
205 for (Iterator<DictEntry> it = matches.iterator(); it.hasNext();) {
206 final DictEntry ee = it.next();
207 if (!ee.getJapanese().equals(kanji)) {
208 it.remove();
209 }
210 }
211 DictEntry.removeInvalid(matches);
212 final DictEntry ee;
213 if (!matches.isEmpty()) {
214 ee = matches.get(0);
215 } else {
216
217 ee = new DictEntry(kanji, "", "");
218 }
219 result.add(ee);
220 }
221 return result;
222 } finally {
223 MiscUtils.closeQuietly(lsEdict);
224 }
225 }
226 }
227 }