Refresh data on "Back", allow configuration of View + border
[jvcard.git] / src / be / nikiroo / jvcard / tui / panes / ContactDetailsRaw.java
CommitLineData
fae07ea7
NR
1package be.nikiroo.jvcard.tui.panes;
2
bcb54330 3import java.util.LinkedList;
fae07ea7
NR
4import java.util.List;
5
6import be.nikiroo.jvcard.Contact;
7import be.nikiroo.jvcard.Data;
bcb54330 8import be.nikiroo.jvcard.TypeInfo;
7da41ecd
NR
9import be.nikiroo.jvcard.launcher.Main;
10import be.nikiroo.jvcard.resources.StringUtils;
11import be.nikiroo.jvcard.resources.Trans;
fae07ea7
NR
12import be.nikiroo.jvcard.tui.KeyAction;
13import be.nikiroo.jvcard.tui.KeyAction.DataType;
14import be.nikiroo.jvcard.tui.KeyAction.Mode;
bcb54330 15import be.nikiroo.jvcard.tui.UiColors.Element;
fae07ea7 16
78e4af97
NR
17import com.googlecode.lanterna.input.KeyType;
18
296a0b75 19public class ContactDetailsRaw extends MainContentList {
fae07ea7 20 private Contact contact;
176a8327 21 private boolean extMode;
fae07ea7 22
296a0b75 23 public ContactDetailsRaw(Contact contact) {
fae07ea7 24 this.contact = contact;
176a8327 25 this.extMode = false;
fae07ea7 26
78e4af97 27 for (int i = 0; i < contact.size(); i++) {
176a8327 28 addItem("x");
fae07ea7
NR
29 }
30 }
31
32 @Override
33 public DataType getDataType() {
bcb54330 34 return DataType.DATA;
fae07ea7 35 }
ae22c247 36
fae07ea7
NR
37 @Override
38 public List<KeyAction> getKeyBindings() {
39 // TODO Auto-generated method stub
bcb54330
NR
40 List<KeyAction> actions = new LinkedList<KeyAction>();
41
42 // TODO: add, remove
78e4af97 43 actions.add(new KeyAction(Mode.ASK_USER, KeyType.Enter,
ae22c247 44 Trans.StringId.DUMMY) {
bcb54330
NR
45 @Override
46 public Object getObject() {
176a8327 47 return getSelectedData();
bcb54330 48 }
ae22c247
NR
49
50 @Override
51 public String getQuestion() {
52 Data data = getData();
53 if (data != null) {
54 return data.getName();
55 }
56
57 return null;
58 }
59
60 @Override
61 public String getDefaultAnswer() {
62 Data data = getData();
63 if (data != null) {
64 return data.getValue();
65 }
66
67 return null;
68 }
69
70 @Override
71 public String callback(String answer) {
72 Data data = getData();
73 if (data != null) {
74 data.setValue(answer);
75 return null;
76 }
77
78 // TODO: i18n
79 return "Cannot modify value";
80 }
bcb54330 81 });
176a8327
NR
82 actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd', Trans.StringId.DUMMY) {
83 @Override
84 public Object getObject() {
85 return getSelectedData();
86 }
87
88 @Override
89 public String getQuestion() {
90 // TODO i18n
91 return "Delete data? [Y/N]";
92 }
93
94 @Override
95 public String callback(String answer) {
96 if (answer.equalsIgnoreCase("y")) {
97 Data data = getData();
98 if (data != null && data.delete()) {
99 removeItem("x");
100 return null;
101 }
102
103 // TODO i18n
104 return "Cannot delete data";
105 }
106
107 return null;
108 }
109 });
110 // TODO: ui
111 actions.add(new KeyAction(Mode.ASK_USER, 'a', Trans.StringId.DUMMY) {
112 @Override
113 public Object getObject() {
114 return contact;
115 }
116
117 @Override
118 public String getQuestion() {
119 // TODO i18n
b9f192ed 120 return "new data (xx.group = yy): ";
176a8327
NR
121 }
122
123 @Override
124 public String callback(String answer) {
b9f192ed
NR
125 int indexEq = answer.indexOf('=');
126 if (indexEq >= 0) {
127 String name = answer.substring(0, indexEq).trim();
128 String value = answer.substring(indexEq + 1).trim();
129 String group = null;
130
131 int indexDt = name.indexOf('.');
132 if (indexDt >= 0) {
133 group = name.substring(indexDt + 1).trim();
134 name = name.substring(0, indexDt).trim();
135 }
136
137 Data data = new Data(null, name, value, group);
176a8327
NR
138 getContact().add(data);
139 addItem("x");
140 }
176a8327
NR
141 return null;
142 }
143 });
144 // TODO: use a real UI for this, not a simple text box (a list or
145 // something, maybe a whole new pane?)
146 actions.add(new KeyAction(Mode.ASK_USER, 't', Trans.StringId.DUMMY) {
147 private String previous;
148
149 @Override
150 public Object getObject() {
151 return getSelectedData();
152 }
153
154 @Override
155 public String getQuestion() {
156 Data data = getData();
157 if (data != null) {
158 return data.getName();
159 }
160
161 return null;
162 }
163
164 @Override
165 public String getDefaultAnswer() {
166 Data data = getData();
167 if (data != null) {
168 previous = typesToString(data, null).toString();
169 return previous;
170 }
171
172 return null;
173 }
174
175 @Override
176 public String callback(String answer) {
177 Data data = getData();
178 if (data != null) {
179 if (!answer.equals(previous)) {
26d2bd05 180 data.replaceListContent(stringToTypes(answer));
176a8327
NR
181 }
182 return null;
183 }
184
185 // TODO: i18n
186 return "Cannot modify value";
187 }
188 });
189 actions.add(new KeyAction(Mode.ASK_USER, 'g', Trans.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 = data.getGroup();
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.setGroup(answer);
224 }
225 return null;
226 }
227
228 // TODO: i18n
229 return "Cannot modify group";
230 }
231 });
bcb54330
NR
232 actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
233 Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
234 @Override
235 public boolean onAction() {
176a8327 236 extMode = !extMode;
bcb54330
NR
237 return false;
238 }
239 });
240
241 return actions;
fae07ea7
NR
242 }
243
fae07ea7
NR
244 @Override
245 public String getTitle() {
0b0b2b0f
NR
246 String title = null;
247
248 if (contact != null) {
249 title = contact.getPreferredDataValue("FN");
250 if (title == null || title.length() == 0)
251 title = contact.getPreferredDataValue("N");
252 }
253
254 return title;
fae07ea7
NR
255 }
256
257 @Override
258 public String move(int x, int y) {
259 // TODO Auto-generated method stub
260 return null;
261 }
f82bad11
NR
262
263 @Override
264 protected List<TextPart> getLabel(int index, int width, boolean selected,
265 boolean focused) {
266 // TODO: from ini file?
267 int SIZE_COL_1 = 15;
176a8327
NR
268 int SIZE_COL_2_OPT = 10;
269
270 if (!extMode)
271 SIZE_COL_2_OPT = 0;
272
273 List<TextPart> parts = new LinkedList<TextPart>();
274 Data data = null;
275 if (index > -1 && index < contact.size())
276 data = contact.get(index);
277
278 if (data == null)
279 return parts;
f82bad11
NR
280
281 Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
282 : Element.CONTACT_LINE;
283 Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
284 : Element.CONTACT_LINE_SEPARATOR;
285 Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
286 : Element.CONTACT_LINE_DIRTY;
287
f82bad11
NR
288 if (data.isDirty()) {
289 parts.add(new TextPart(" ", el));
290 parts.add(new TextPart("*", elDirty));
291 } else {
292 parts.add(new TextPart(" ", elSep));
293 }
294 String name = " " + data.getName() + " ";
295 String value = null;
176a8327 296 String group = null;
f82bad11
NR
297
298 StringBuilder valueBuilder = new StringBuilder(" ");
176a8327 299 if (!extMode) {
f82bad11
NR
300 valueBuilder.append(data.getValue());
301 if (data.getGroup() != null && data.getGroup().length() > 0) {
302 valueBuilder.append("(");
303 valueBuilder.append(data.getGroup());
304 valueBuilder.append(")");
305 }
176a8327
NR
306 } else {
307 group = data.getGroup();
308 if (group == null)
309 group = "";
310
311 typesToString(data, valueBuilder);
f82bad11
NR
312 }
313 valueBuilder.append(" ");
314
315 value = valueBuilder.toString();
316
7da41ecd
NR
317 name = StringUtils.sanitize(name, Main.isUnicode());
318 value = StringUtils.sanitize(value, Main.isUnicode());
f82bad11
NR
319
320 name = StringUtils.padString(name, SIZE_COL_1);
176a8327 321 group = StringUtils.padString(group, SIZE_COL_2_OPT);
f82bad11 322 value = StringUtils.padString(value, width - SIZE_COL_1
176a8327
NR
323 - SIZE_COL_2_OPT - (extMode ? 2 : 1) * getSeparator().length()
324 - 2);
f82bad11
NR
325
326 parts.add(new TextPart(name, el));
327 parts.add(new TextPart(getSeparator(), elSep));
328 parts.add(new TextPart(value, el));
176a8327
NR
329 if (extMode) {
330 parts.add(new TextPart(getSeparator(), elSep));
331 parts.add(new TextPart(group, el));
332 }
f82bad11
NR
333
334 return parts;
176a8327
NR
335 }
336
337 /**
338 * Return the currently selected {@link Data}.
339 *
340 * @return the currently selected {@link Data}
341 */
342 private Data getSelectedData() {
343 int index = getSelectedIndex();
344 if (index > -1 && index < this.contact.size())
345 return contact.get(index);
346 return null;
347 }
348
349 /**
350 * Serialise the {@link TypeInfo}s in the given {@link Data}.
351 *
352 * @param data
353 * the {@link Data} from which to take the {@link TypeInfo}s
354 * @param builder
355 * an optional {@link StringBuilder} to append the serialized
356 * version to
357 *
358 * @return the given {@link StringBuilder} or a new one if the given one is
359 * NULL
360 */
361 static private StringBuilder typesToString(Data data, StringBuilder builder) {
362 if (builder == null)
363 builder = new StringBuilder();
364
365 for (int indexType = 0; indexType < data.size(); indexType++) {
366 TypeInfo type = data.get(indexType);
367 if (builder.length() > 1)
368 builder.append(", ");
369 builder.append(type.getName().replaceAll(",", "\\,"));
370 builder.append(": ");
371 builder.append(type.getValue().replaceAll(":", "\\:"));
372 }
373
374 return builder;
375 }
f82bad11 376
176a8327
NR
377 /**
378 * Unserialise a list of {@link TypeInfo}s.
379 *
380 * @param value
381 * the serialised value
382 *
383 * @return the {@link TypeInfo} in their object form
384 */
385 static private List<TypeInfo> stringToTypes(String value) {
386 List<TypeInfo> infos = new LinkedList<TypeInfo>();
387 if (value == null || value.length() == 0)
388 return infos;
389
390 char previous = '\0';
391 char car = '\0';
392 int done = 0;
393 for (int index = 0; index < value.length(); index++) {
394 car = value.charAt(index);
395 if (index == value.length() - 1) {
396 index++;
397 previous = '\0';
398 car = ',';
399 }
400
401 if (previous != '\\' && car == ',') {
402 String[] tab = value.substring(done, index).split("\\:");
403 infos.add(new TypeInfo( //
404 tab[0].replaceAll("\\,", ",").replaceAll("\\:", ":")
405 .trim(), //
406 tab[1].replaceAll("\\,", ",").replaceAll("\\:", ":")
407 .trim()));
408 done = index + 1;
409 }
410
411 previous = car;
412 }
413
414 return infos;
415 }
fae07ea7 416}