Beta2 relase
[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.i18n.Trans;
10 import be.nikiroo.jvcard.tui.KeyAction;
11 import be.nikiroo.jvcard.tui.KeyAction.DataType;
12 import be.nikiroo.jvcard.tui.KeyAction.Mode;
13 import be.nikiroo.jvcard.tui.StringUtils;
14 import be.nikiroo.jvcard.tui.UiColors;
15 import be.nikiroo.jvcard.tui.UiColors.Element;
16
17 import com.googlecode.lanterna.input.KeyType;
18
19 public class ContactDetailsRaw extends MainContentList {
20 private Contact contact;
21 private boolean extMode;
22
23 public ContactDetailsRaw(Contact contact) {
24 this.contact = contact;
25 this.extMode = false;
26
27 for (int i = 0; i < contact.size(); i++) {
28 addItem("x");
29 }
30 }
31
32 @Override
33 public DataType getDataType() {
34 return DataType.DATA;
35 }
36
37 @Override
38 public List<KeyAction> getKeyBindings() {
39 // TODO Auto-generated method stub
40 List<KeyAction> actions = new LinkedList<KeyAction>();
41
42 // TODO: add, remove
43 actions.add(new KeyAction(Mode.ASK_USER, KeyType.Enter,
44 Trans.StringId.DUMMY) {
45 @Override
46 public Object getObject() {
47 return getSelectedData();
48 }
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 }
81 });
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
120 return "new data (xx = yy): ";
121 }
122
123 @Override
124 public String callback(String answer) {
125 if (answer.length() > 0 && answer.contains("=")) {
126 String[] tab = answer.split("=");
127 Data data = new Data(null, tab[0].trim(), tab[1].trim(),
128 null);
129 getContact().add(data);
130 addItem("x");
131 }
132
133 return null;
134 }
135 });
136 // TODO: use a real UI for this, not a simple text box (a list or
137 // something, maybe a whole new pane?)
138 actions.add(new KeyAction(Mode.ASK_USER, 't', Trans.StringId.DUMMY) {
139 private String previous;
140
141 @Override
142 public Object getObject() {
143 return getSelectedData();
144 }
145
146 @Override
147 public String getQuestion() {
148 Data data = getData();
149 if (data != null) {
150 return data.getName();
151 }
152
153 return null;
154 }
155
156 @Override
157 public String getDefaultAnswer() {
158 Data data = getData();
159 if (data != null) {
160 previous = typesToString(data, null).toString();
161 return previous;
162 }
163
164 return null;
165 }
166
167 @Override
168 public String callback(String answer) {
169 Data data = getData();
170 if (data != null) {
171 if (!answer.equals(previous)) {
172 data.setTypes(stringToTypes(answer));
173 }
174 return null;
175 }
176
177 // TODO: i18n
178 return "Cannot modify value";
179 }
180 });
181 actions.add(new KeyAction(Mode.ASK_USER, 'g', Trans.StringId.DUMMY) {
182 private String previous;
183
184 @Override
185 public Object getObject() {
186 return getSelectedData();
187 }
188
189 @Override
190 public String getQuestion() {
191 Data data = getData();
192 if (data != null) {
193 return data.getName();
194 }
195
196 return null;
197 }
198
199 @Override
200 public String getDefaultAnswer() {
201 Data data = getData();
202 if (data != null) {
203 previous = data.getGroup();
204 return previous;
205 }
206
207 return null;
208 }
209
210 @Override
211 public String callback(String answer) {
212 Data data = getData();
213 if (data != null) {
214 if (!answer.equals(previous)) {
215 data.setGroup(answer);
216 }
217 return null;
218 }
219
220 // TODO: i18n
221 return "Cannot modify group";
222 }
223 });
224 actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
225 Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
226 @Override
227 public boolean onAction() {
228 extMode = !extMode;
229 return false;
230 }
231 });
232
233 return actions;
234 }
235
236 @Override
237 public String getTitle() {
238 String title = null;
239
240 if (contact != null) {
241 title = contact.getPreferredDataValue("FN");
242 if (title == null || title.length() == 0)
243 title = contact.getPreferredDataValue("N");
244 }
245
246 return title;
247 }
248
249 @Override
250 public String move(int x, int y) {
251 // TODO Auto-generated method stub
252 return null;
253 }
254
255 @Override
256 protected List<TextPart> getLabel(int index, int width, boolean selected,
257 boolean focused) {
258 // TODO: from ini file?
259 int SIZE_COL_1 = 15;
260 int SIZE_COL_2_OPT = 10;
261
262 if (!extMode)
263 SIZE_COL_2_OPT = 0;
264
265 List<TextPart> parts = new LinkedList<TextPart>();
266 Data data = null;
267 if (index > -1 && index < contact.size())
268 data = contact.get(index);
269
270 if (data == null)
271 return parts;
272
273 Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
274 : Element.CONTACT_LINE;
275 Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
276 : Element.CONTACT_LINE_SEPARATOR;
277 Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
278 : Element.CONTACT_LINE_DIRTY;
279
280 if (data.isDirty()) {
281 parts.add(new TextPart(" ", el));
282 parts.add(new TextPart("*", elDirty));
283 } else {
284 parts.add(new TextPart(" ", elSep));
285 }
286 String name = " " + data.getName() + " ";
287 String value = null;
288 String group = null;
289
290 StringBuilder valueBuilder = new StringBuilder(" ");
291 if (!extMode) {
292 valueBuilder.append(data.getValue());
293 if (data.getGroup() != null && data.getGroup().length() > 0) {
294 valueBuilder.append("(");
295 valueBuilder.append(data.getGroup());
296 valueBuilder.append(")");
297 }
298 } else {
299 group = data.getGroup();
300 if (group == null)
301 group = "";
302
303 typesToString(data, valueBuilder);
304 }
305 valueBuilder.append(" ");
306
307 value = valueBuilder.toString();
308
309 name = StringUtils.sanitize(name, UiColors.getInstance().isUnicode());
310 value = StringUtils.sanitize(value, UiColors.getInstance().isUnicode());
311
312 name = StringUtils.padString(name, SIZE_COL_1);
313 group = StringUtils.padString(group, SIZE_COL_2_OPT);
314 value = StringUtils.padString(value, width - SIZE_COL_1
315 - SIZE_COL_2_OPT - (extMode ? 2 : 1) * getSeparator().length()
316 - 2);
317
318 parts.add(new TextPart(name, el));
319 parts.add(new TextPart(getSeparator(), elSep));
320 parts.add(new TextPart(value, el));
321 if (extMode) {
322 parts.add(new TextPart(getSeparator(), elSep));
323 parts.add(new TextPart(group, el));
324 }
325
326 return parts;
327 }
328
329 /**
330 * Return the currently selected {@link Data}.
331 *
332 * @return the currently selected {@link Data}
333 */
334 private Data getSelectedData() {
335 int index = getSelectedIndex();
336 if (index > -1 && index < this.contact.size())
337 return contact.get(index);
338 return null;
339 }
340
341 /**
342 * Serialise the {@link TypeInfo}s in the given {@link Data}.
343 *
344 * @param data
345 * the {@link Data} from which to take the {@link TypeInfo}s
346 * @param builder
347 * an optional {@link StringBuilder} to append the serialized
348 * version to
349 *
350 * @return the given {@link StringBuilder} or a new one if the given one is
351 * NULL
352 */
353 static private StringBuilder typesToString(Data data, StringBuilder builder) {
354 if (builder == null)
355 builder = new StringBuilder();
356
357 for (int indexType = 0; indexType < data.size(); indexType++) {
358 TypeInfo type = data.get(indexType);
359 if (builder.length() > 1)
360 builder.append(", ");
361 builder.append(type.getName().replaceAll(",", "\\,"));
362 builder.append(": ");
363 builder.append(type.getValue().replaceAll(":", "\\:"));
364 }
365
366 return builder;
367 }
368
369 /**
370 * Unserialise a list of {@link TypeInfo}s.
371 *
372 * @param value
373 * the serialised value
374 *
375 * @return the {@link TypeInfo} in their object form
376 */
377 static private List<TypeInfo> stringToTypes(String value) {
378 List<TypeInfo> infos = new LinkedList<TypeInfo>();
379 if (value == null || value.length() == 0)
380 return infos;
381
382 char previous = '\0';
383 char car = '\0';
384 int done = 0;
385 for (int index = 0; index < value.length(); index++) {
386 car = value.charAt(index);
387 if (index == value.length() - 1) {
388 index++;
389 previous = '\0';
390 car = ',';
391 }
392
393 if (previous != '\\' && car == ',') {
394 String[] tab = value.substring(done, index).split("\\:");
395 infos.add(new TypeInfo( //
396 tab[0].replaceAll("\\,", ",").replaceAll("\\:", ":")
397 .trim(), //
398 tab[1].replaceAll("\\,", ",").replaceAll("\\:", ":")
399 .trim()));
400 done = index + 1;
401 }
402
403 previous = car;
404 }
405
406 return infos;
407 }
408 }