KeyAction management now more generic
[jvcard.git] / src / be / nikiroo / jvcard / tui / panes / ContactList.java
CommitLineData
fae07ea7
NR
1package be.nikiroo.jvcard.tui.panes;
2
ae22c247 3import java.io.IOException;
fae07ea7
NR
4import java.util.LinkedList;
5import java.util.List;
6
7import be.nikiroo.jvcard.Card;
0b0b2b0f 8import be.nikiroo.jvcard.Contact;
fae07ea7
NR
9import be.nikiroo.jvcard.i18n.Trans;
10import be.nikiroo.jvcard.tui.KeyAction;
11import be.nikiroo.jvcard.tui.UiColors;
12import be.nikiroo.jvcard.tui.KeyAction.DataType;
13import be.nikiroo.jvcard.tui.KeyAction.Mode;
9c8baf0c 14import be.nikiroo.jvcard.tui.UiColors.Element;
fae07ea7
NR
15
16import com.googlecode.lanterna.input.KeyType;
17
18public class ContactList extends MainContentList {
19 private Card card;
ae22c247
NR
20 private List<Contact> contacts;
21 private String filter;
fae07ea7
NR
22
23 private List<String> formats = new LinkedList<String>();
24 private int selectedFormat = -1;
25 private String format = "";
26
27 public ContactList(Card card) {
28 super(UiColors.Element.CONTACT_LINE,
29 UiColors.Element.CONTACT_LINE_SELECTED);
30
31 // TODO: should get that in an INI file
32 formats.add("NICKNAME@3|FN@+|EMAIL@30");
33 formats.add("FN@+|EMAIL@40");
34 switchFormat();
35
36 setCard(card);
37 }
38
39 /**
ae22c247
NR
40 * Change the currently displayed contacts card, only allowing those that
41 * satisfy the current filter.
fae07ea7
NR
42 *
43 * @param card
44 * the new {@link Card}
ae22c247
NR
45 * @param filter
46 * the text filter or NULL for all contacts
fae07ea7
NR
47 */
48 public void setCard(Card card) {
49 clearItems();
50 this.card = card;
ae22c247 51 this.contacts = new LinkedList<Contact>();
fae07ea7
NR
52
53 if (card != null) {
54 for (int i = 0; i < card.getContacts().size(); i++) {
ae22c247
NR
55 Contact c = card.getContacts().get(i);
56 if (filter == null
57 || c.toString(format).toLowerCase()
58 .contains(filter.toLowerCase())) {
59 addItem("[contact line]");
60 contacts.add(c);
61 }
fae07ea7
NR
62 }
63 }
64
65 setSelectedIndex(0);
66 }
67
bcb54330
NR
68 @Override
69 public void refreshData() {
70 int index = getSelectedIndex();
71 setCard(card);
ae22c247
NR
72 if (index >= contacts.size())
73 index = contacts.size() - 1;
bcb54330 74 setSelectedIndex(index);
ae22c247 75
bcb54330
NR
76 super.refreshData();
77 }
78
fae07ea7
NR
79 @Override
80 public String getExitWarning() {
81 if (card != null && card.isDirty()) {
bcb54330 82 return "Ignore unsaved changes? [Y/N]";
fae07ea7 83 }
bcb54330 84
fae07ea7
NR
85 return null;
86 }
87
88 @Override
89 public List<KeyAction> getKeyBindings() {
90 List<KeyAction> actions = new LinkedList<KeyAction>();
91
296a0b75 92 // TODO add
f04d8b1c 93 actions.add(new KeyAction(Mode.CONTACT_DETAILS_RAW, 'e',
bcb54330 94 Trans.StringId.KEY_ACTION_EDIT_CONTACT) {
0b0b2b0f 95 @Override
bcb54330
NR
96 public Object getObject() {
97 return getSelectedContact();
0b0b2b0f
NR
98 }
99 });
ae22c247 100 actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd',
bcb54330
NR
101 Trans.StringId.KEY_ACTION_DELETE_CONTACT) {
102 @Override
103 public Object getObject() {
104 return getSelectedContact();
105 }
ae22c247
NR
106
107 @Override
108 public String getQuestion() {
109 // TODO i18n
110 return "Delete contact? [Y/N]";
111 }
112
113 @Override
114 public String callback(String answer) {
115 if (answer.equalsIgnoreCase("y")) {
116 Contact contact = getSelectedContact();
117 if (contact != null && contact.delete()) {
118 return null;
119 }
120
121 // TODO i18n
122 return "Cannot delete contact";
123 }
124
125 return null;
126 }
bcb54330 127 });
ae22c247 128 actions.add(new KeyAction(Mode.ASK_USER_KEY, 's',
bcb54330 129 Trans.StringId.KEY_ACTION_SAVE_CARD) {
fae07ea7
NR
130 @Override
131 public Object getObject() {
bcb54330 132 return card;
fae07ea7 133 }
ae22c247
NR
134
135 @Override
136 public String getQuestion() {
137 return "Save changes? [Y/N]";
138 }
139
140 @Override
141 public String callback(String answer) {
142 if (answer.equalsIgnoreCase("y")) {
143 boolean ok = false;
144 try {
145 if (card != null && card.save())
146 ok = true;
147 } catch (IOException ioe) {
148 ioe.printStackTrace();
149 }
150
151 if (!ok) {
152 return "Cannot save to file";
153 }
154 }
155
156 return null;
157 }
158
fae07ea7
NR
159 });
160 actions.add(new KeyAction(Mode.CONTACT_DETAILS, KeyType.Enter,
161 Trans.StringId.KEY_ACTION_VIEW_CONTACT) {
162 @Override
163 public Object getObject() {
bcb54330 164 return getSelectedContact();
fae07ea7
NR
165 }
166 });
bcb54330 167 actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
fae07ea7
NR
168 Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
169 @Override
170 public boolean onAction() {
171 switchFormat();
172 return false;
173 }
174 });
ae22c247
NR
175 actions.add(new KeyAction(Mode.ASK_USER, 'w',
176 Trans.StringId.KEY_ACTION_SEARCH) {
177
178 @Override
179 public String getQuestion() {
180 return "Search:";
181 }
182
183 @Override
184 public String getDefaultAnswer() {
185 return filter;
186 }
187
188 @Override
189 public String callback(String answer) {
190 filter = answer;
191 setCard(card);
192 return null;
193 }
194 });
fae07ea7
NR
195
196 return actions;
197 }
198
199 @Override
200 public DataType getDataType() {
201 return DataType.CARD;
202 }
203
fae07ea7
NR
204 @Override
205 public String getTitle() {
0b0b2b0f 206 if (card != null) {
ae22c247
NR
207 if (filter != null)
208 return card.getName() + " [" + filter + "]";
0b0b2b0f
NR
209 return card.getName();
210 }
211
fae07ea7
NR
212 return null;
213 }
214
215 @Override
9c8baf0c
NR
216 protected List<TextPart> getLabel(int index, int width, boolean selected,
217 boolean focused) {
bcb54330
NR
218 List<TextPart> parts = new LinkedList<TextPart>();
219
220 Contact contact = null;
ae22c247
NR
221 if (index > -1 && index < contacts.size())
222 contact = contacts.get(index);
bcb54330
NR
223
224 if (contact == null)
225 return parts;
9c8baf0c
NR
226
227 Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
228 : Element.CONTACT_LINE;
229 Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
230 : Element.CONTACT_LINE_SEPARATOR;
0b0b2b0f
NR
231 Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
232 : Element.CONTACT_LINE_DIRTY;
9c8baf0c 233
0b0b2b0f 234 width -= 2; // dirty mark space
9c8baf0c 235
bcb54330 236 String[] array = contact.toStringArray(format, getSeparator(), " ",
296a0b75 237 width, UiColors.getInstance().isUnicode());
0b0b2b0f 238
bcb54330 239 if (contact.isDirty()) {
0b0b2b0f
NR
240 parts.add(new TextPart(" ", el));
241 parts.add(new TextPart("*", elDirty));
242 } else {
243 parts.add(new TextPart(" ", elSep));
9c8baf0c
NR
244 }
245
0b0b2b0f
NR
246 boolean separator = false;
247 for (String str : array) {
248 parts.add(new TextPart(str, (separator ? elSep : el)));
249 separator = !separator;
250 }
9c8baf0c
NR
251
252 return parts;
fae07ea7
NR
253 }
254
bcb54330
NR
255 /**
256 * Return the currently selected {@link Contact}.
257 *
258 * @return the currently selected {@link Contact}
259 */
260 private Contact getSelectedContact() {
261 int index = getSelectedIndex();
ae22c247
NR
262 if (index > -1 && index < contacts.size())
263 return contacts.get(index);
bcb54330
NR
264 return null;
265 }
266
fae07ea7
NR
267 private void switchFormat() {
268 if (formats.size() == 0)
269 return;
270
271 selectedFormat++;
272 if (selectedFormat >= formats.size()) {
273 selectedFormat = 0;
274 }
275
276 format = formats.get(selectedFormat);
277
278 invalidate();
279 }
280}