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