Fix inclusion of lanterna's resources + fix warning
[jvcard.git] / src / be / nikiroo / jvcard / tui / panes / ContactDetailsRaw.java
1 package be.nikiroo.jvcard.tui.panes;
2
3 import java.util.LinkedList;
4 import java.util.List;
5
6 import be.nikiroo.jvcard.Contact;
7 import be.nikiroo.jvcard.Data;
8 import be.nikiroo.jvcard.TypeInfo;
9 import be.nikiroo.jvcard.launcher.Main;
10 import be.nikiroo.jvcard.resources.StringUtils;
11 import be.nikiroo.jvcard.resources.enums.ColorOption;
12 import be.nikiroo.jvcard.resources.enums.StringId;
13 import be.nikiroo.jvcard.tui.KeyAction;
14 import be.nikiroo.jvcard.tui.KeyAction.DataType;
15 import be.nikiroo.jvcard.tui.KeyAction.Mode;
16 import be.nikiroo.jvcard.tui.TuiLauncher;
17
18 import com.googlecode.lanterna.gui2.MultiWindowTextGUI;
19 import com.googlecode.lanterna.gui2.dialogs.ActionListDialogBuilder;
20 import com.googlecode.lanterna.input.KeyType;
21
22 public class ContactDetailsRaw extends MainContentList {
23 private Contact contact;
24 private boolean extMode;
25
26 public ContactDetailsRaw(Contact contact) {
27 this.contact = contact;
28 this.extMode = false;
29
30 for (int i = 0; i < contact.size(); i++) {
31 addItem("x");
32 }
33 }
34
35 @Override
36 public DataType getDataType() {
37 return DataType.DATA;
38 }
39
40 @Override
41 public List<KeyAction> getKeyBindings() {
42 List<KeyAction> actions = new LinkedList<KeyAction>();
43
44 actions.add(new KeyAction(Mode.ASK_USER, KeyType.Enter,
45 StringId.KEY_ACTION_EDIT_FIELD) {
46 @Override
47 public Object getObject() {
48 Data data = getSelectedData();
49 if (data != null && data.getB64Key() != -1) {
50 setMessage("Cannot modify binary values in RAW mode", true);
51 data = null;
52 }
53
54 return data;
55 }
56
57 @Override
58 public String getQuestion() {
59 Data data = getData();
60 if (data != null) {
61 return data.getName();
62 }
63
64 return null;
65 }
66
67 @Override
68 public String getDefaultAnswer() {
69 Data data = getData();
70 if (data != null) {
71 return data.getRawValue().replaceAll("\n", "\\\\n");
72 }
73
74 return null;
75 }
76
77 @Override
78 public String callback(String answer) {
79 Data data = getData();
80 if (data != null) {
81 data.setRawValue(answer.replaceAll("\\\\n", "\n"));
82 return null;
83 }
84
85 // TODO: i18n
86 return "Cannot modify value";
87 }
88 });
89 actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd',
90 StringId.KEY_ACTION_DELETE) {
91 @Override
92 public Object getObject() {
93 return getSelectedData();
94 }
95
96 @Override
97 public String getQuestion() {
98 // TODO i18n
99 return "Delete data? [Y/N]";
100 }
101
102 @Override
103 public String callback(String answer) {
104 if (answer.equalsIgnoreCase("y")) {
105 Data data = getData();
106 if (data != null && data.delete()) {
107 removeItem("x");
108 return null;
109 }
110
111 // TODO i18n
112 return "Cannot delete data";
113 }
114
115 return null;
116 }
117 });
118 // TODO: ui
119 actions.add(new KeyAction(Mode.ASK_USER, 'a', StringId.KEY_ACTION_ADD) {
120 @Override
121 public boolean onAction() {
122 try{
123 new ActionListDialogBuilder()
124 .setTitle("Action List Dialog")
125 .setDescription("Choose an item")
126 .addAction("First Item", new Runnable() {
127 @Override
128 public void run() {
129 // Do 1st thing...
130 }
131 })
132 .addAction("Second Item", new Runnable() {
133 @Override
134 public void run() {
135 // Do 2nd thing...
136 }
137 })
138 .addAction("Third Item", new Runnable() {
139 @Override
140 public void run() {
141 // Do 3rd thing...
142 }
143 })
144 .build()
145 .showDialog(
146 new MultiWindowTextGUI(TuiLauncher.getScreen()));
147
148 return true;
149 }catch(Exception e){
150 e.printStackTrace();
151 throw e;
152 }
153 }
154
155 @Override
156 public Object getObject() {
157 return contact;
158 }
159
160 @Override
161 public String getQuestion() {
162 // TODO i18n
163 return "new data (xx.group = yy): ";
164 }
165
166 @Override
167 public String callback(String answer) {
168 int indexEq = answer.indexOf('=');
169 if (indexEq >= 0) {
170 String name = answer.substring(0, indexEq).trim();
171 String value = answer.substring(indexEq + 1).trim();
172 String group = null;
173
174 int indexDt = name.indexOf('.');
175 if (indexDt >= 0) {
176 group = name.substring(indexDt + 1).trim();
177 name = name.substring(0, indexDt).trim();
178 }
179
180 Data data = new Data(null, name, value, group);
181 getContact().add(data);
182 addItem("x");
183 }
184 return null;
185 }
186 });
187 // TODO: use a real UI for this, not a simple text box (a list or
188 // something, maybe a whole new pane?)
189 actions.add(new KeyAction(Mode.ASK_USER, 't', StringId.DUMMY) {
190 private String previous;
191
192 @Override
193 public Object getObject() {
194 return getSelectedData();
195 }
196
197 @Override
198 public String getQuestion() {
199 Data data = getData();
200 if (data != null) {
201 return data.getName();
202 }
203
204 return null;
205 }
206
207 @Override
208 public String getDefaultAnswer() {
209 Data data = getData();
210 if (data != null) {
211 previous = typesToString(data, null).toString();
212 return previous;
213 }
214
215 return null;
216 }
217
218 @Override
219 public String callback(String answer) {
220 Data data = getData();
221 if (data != null) {
222 if (!answer.equals(previous)) {
223 data.replaceListContent(stringToTypes(answer));
224 }
225 return null;
226 }
227
228 // TODO: i18n
229 return "Cannot modify value";
230 }
231 });
232 actions.add(new KeyAction(Mode.ASK_USER, 'g', StringId.DUMMY) {
233 private String previous;
234
235 @Override
236 public Object getObject() {
237 return getSelectedData();
238 }
239
240 @Override
241 public String getQuestion() {
242 Data data = getData();
243 if (data != null) {
244 return data.getName();
245 }
246
247 return null;
248 }
249
250 @Override
251 public String getDefaultAnswer() {
252 Data data = getData();
253 if (data != null) {
254 previous = data.getGroup();
255 return previous;
256 }
257
258 return null;
259 }
260
261 @Override
262 public String callback(String answer) {
263 Data data = getData();
264 if (data != null) {
265 if (!answer.equals(previous)) {
266 data.setGroup(answer);
267 }
268 return null;
269 }
270
271 // TODO: i18n
272 return "Cannot modify group";
273 }
274 });
275 actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
276 StringId.KEY_ACTION_SWITCH_FORMAT) {
277 @Override
278 public boolean onAction() {
279 extMode = !extMode;
280 return false;
281 }
282 });
283
284 return actions;
285 }
286
287 @Override
288 public String getTitle() {
289 String title = null;
290
291 if (contact != null) {
292 title = contact.getPreferredDataValue("FN");
293 if (title == null || title.length() == 0)
294 title = contact.getPreferredDataValue("N");
295 }
296
297 return title;
298 }
299
300 @Override
301 public String move(int x, int y) {
302 // TODO Auto-generated method stub
303 return null;
304 }
305
306 @Override
307 protected List<TextPart> getLabel(int index, int width, boolean selected,
308 boolean focused) {
309
310 // TODO: from ini file?
311 int SIZE_COL_1 = 15;
312 int SIZE_COL_2_OPT = 10;
313
314 if (!extMode)
315 SIZE_COL_2_OPT = 0;
316
317 List<TextPart> parts = new LinkedList<TextPart>();
318 Data data = null;
319 if (index > -1 && index < contact.size())
320 data = contact.get(index);
321
322 if (data == null)
323 return parts;
324
325 ColorOption el = (focused && selected) ? ColorOption.CONTACT_LINE_SELECTED
326 : ColorOption.CONTACT_LINE;
327 ColorOption elSep = (focused && selected) ? ColorOption.CONTACT_LINE_SEPARATOR_SELECTED
328 : ColorOption.CONTACT_LINE_SEPARATOR;
329 ColorOption elDirty = (focused && selected) ? ColorOption.CONTACT_LINE_DIRTY_SELECTED
330 : ColorOption.CONTACT_LINE_DIRTY;
331
332 if (data.isDirty()) {
333 parts.add(new TextPart(" ", el));
334 parts.add(new TextPart("*", elDirty));
335 } else {
336 parts.add(new TextPart(" ", elSep));
337 }
338 String name = " " + data.getName() + " ";
339 String value = null;
340 String group = null;
341
342 StringBuilder valueBuilder = new StringBuilder(" ");
343 if (!extMode) {
344 if (data.getB64Key() != -1) {
345 // TODO: i18n
346 valueBuilder.append("<BKey " + data.getB64Key() + ">");
347 } else {
348 valueBuilder.append(data.getValue().replaceAll("\n", "\\\\n"));
349 }
350 if (data.getGroup() != null && data.getGroup().length() > 0) {
351 valueBuilder.append("(");
352 valueBuilder.append(data.getGroup());
353 valueBuilder.append(")");
354 }
355 } else {
356 group = data.getGroup();
357 if (group == null)
358 group = "";
359
360 typesToString(data, valueBuilder);
361 }
362 valueBuilder.append(" ");
363
364 value = valueBuilder.toString();
365
366 name = StringUtils.sanitize(name, Main.isUnicode());
367 value = StringUtils.sanitize(value, Main.isUnicode());
368
369 name = StringUtils.padString(name, SIZE_COL_1);
370 group = StringUtils.padString(group, SIZE_COL_2_OPT);
371 value = StringUtils.padString(value, width - SIZE_COL_1
372 - SIZE_COL_2_OPT - (extMode ? 2 : 1) * getSeparator().length()
373 - 2);
374
375 parts.add(new TextPart(name, el));
376 parts.add(new TextPart(getSeparator(), elSep));
377 parts.add(new TextPart(value, el));
378 if (extMode) {
379 parts.add(new TextPart(getSeparator(), elSep));
380 parts.add(new TextPart(group, el));
381 }
382
383 return parts;
384 }
385
386 /**
387 * Return the currently selected {@link Data}.
388 *
389 * @return the currently selected {@link Data}
390 */
391 private Data getSelectedData() {
392 int index = getSelectedIndex();
393 if (index > -1 && index < this.contact.size())
394 return contact.get(index);
395 return null;
396 }
397
398 /**
399 * Serialise the {@link TypeInfo}s in the given {@link Data}.
400 *
401 * @param data
402 * the {@link Data} from which to take the {@link TypeInfo}s
403 * @param builder
404 * an optional {@link StringBuilder} to append the serialised
405 * version to
406 *
407 * @return the given {@link StringBuilder} or a new one if the given one is
408 * NULL
409 */
410 static private StringBuilder typesToString(Data data, StringBuilder builder) {
411 if (builder == null)
412 builder = new StringBuilder();
413
414 for (TypeInfo type : data) {
415 if (builder.length() > 1)
416 builder.append(", ");
417 builder.append(type.getName().replaceAll(",", "\\,"));
418 builder.append(": ");
419 builder.append(type.getValue().replaceAll(":", "\\:"));
420 }
421
422 return builder;
423 }
424
425 /**
426 * Unserialise a list of {@link TypeInfo}s.
427 *
428 * @param value
429 * the serialised value
430 *
431 * @return the {@link TypeInfo} in their object form
432 */
433 static private List<TypeInfo> stringToTypes(String value) {
434 List<TypeInfo> infos = new LinkedList<TypeInfo>();
435 if (value == null || value.length() == 0)
436 return infos;
437
438 char previous = '\0';
439 char car = '\0';
440 int done = 0;
441 for (int index = 0; index < value.length(); index++) {
442 car = value.charAt(index);
443 if (index == value.length() - 1) {
444 index++;
445 previous = '\0';
446 car = ',';
447 }
448
449 if (previous != '\\' && car == ',') {
450 String subValue = value.substring(done, index);
451 int indexColumn = subValue.indexOf(':');
452 while (indexColumn > 0
453 && subValue.charAt(indexColumn - 1) == '\\') {
454 if (indexColumn == subValue.length() - 1) {
455 indexColumn = -1;
456 } else {
457 indexColumn = subValue.indexOf(':', indexColumn + 1);
458 }
459 }
460
461 String n = "";
462 String v = "";
463 if (indexColumn >= 0) {
464 n = subValue.substring(0, indexColumn).trim();
465 v = subValue.substring(indexColumn + 1)
466 .replaceAll("\\\\:", ":").trim();
467 } else {
468 n = subValue.trim();
469 }
470
471 infos.add(new TypeInfo(n, v));
472
473 done = index + 1;
474 }
475
476 previous = car;
477 }
478
479 return infos;
480 }
481 }