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