6287a69997caf3bcee592ca394b738c83aff70f0
[jvcard.git] / src / be / nikiroo / jvcard / tui / panes / ContactList.java
1 package be.nikiroo.jvcard.tui.panes;
2
3 import java.io.IOException;
4 import java.util.LinkedList;
5 import java.util.List;
6
7 import be.nikiroo.jvcard.Card;
8 import be.nikiroo.jvcard.Contact;
9 import be.nikiroo.jvcard.i18n.Trans;
10 import be.nikiroo.jvcard.resources.Bundles;
11 import be.nikiroo.jvcard.tui.KeyAction;
12 import be.nikiroo.jvcard.tui.UiColors;
13 import be.nikiroo.jvcard.tui.KeyAction.DataType;
14 import be.nikiroo.jvcard.tui.KeyAction.Mode;
15 import be.nikiroo.jvcard.tui.UiColors.Element;
16
17 import com.googlecode.lanterna.input.KeyType;
18
19 public class ContactList extends MainContentList {
20 private Card card;
21 private List<Contact> contacts;
22 private String filter;
23
24 private List<String> formats;
25 private int selectedFormat;
26 private String format;
27
28 public ContactList(Card card) {
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;
36 switchFormat();
37
38 setCard(card);
39 }
40
41 /**
42 * Change the currently displayed contacts card, only allowing those that
43 * satisfy the current filter.
44 *
45 * @param card
46 * the new {@link Card}
47 * @param filter
48 * the text filter or NULL for all contacts
49 */
50 public void setCard(Card card) {
51 clearItems();
52 this.card = card;
53 this.contacts = new LinkedList<Contact>();
54
55 if (card != null) {
56 for (int i = 0; i < card.size(); i++) {
57 Contact c = card.get(i);
58 if (filter == null
59 || c.toString(format).toLowerCase()
60 .contains(filter.toLowerCase())) {
61 addItem("[contact line]");
62 contacts.add(c);
63 }
64 }
65 }
66
67 setSelectedIndex(0);
68 }
69
70 @Override
71 public void refreshData() {
72 int index = getSelectedIndex();
73 setCard(card);
74 if (index >= contacts.size())
75 index = contacts.size() - 1;
76 setSelectedIndex(index);
77
78 super.refreshData();
79 }
80
81 @Override
82 public String getExitWarning() {
83 if (card != null && card.isDirty()) {
84 return "Ignore unsaved changes? [Y/N]";
85 }
86
87 return null;
88 }
89
90 @Override
91 public List<KeyAction> getKeyBindings() {
92 List<KeyAction> actions = new LinkedList<KeyAction>();
93
94 // TODO add
95 actions.add(new KeyAction(Mode.CONTACT_DETAILS_RAW, 'e',
96 Trans.StringId.KEY_ACTION_EDIT_CONTACT) {
97 @Override
98 public Object getObject() {
99 return getSelectedContact();
100 }
101 });
102 actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd',
103 Trans.StringId.KEY_ACTION_DELETE_CONTACT) {
104 @Override
105 public Object getObject() {
106 return getSelectedContact();
107 }
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 }
129 });
130 actions.add(new KeyAction(Mode.ASK_USER_KEY, 's',
131 Trans.StringId.KEY_ACTION_SAVE_CARD) {
132 @Override
133 public Object getObject() {
134 return card;
135 }
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
161 });
162 actions.add(new KeyAction(Mode.CONTACT_DETAILS, KeyType.Enter,
163 Trans.StringId.KEY_ACTION_VIEW_CONTACT) {
164 @Override
165 public Object getObject() {
166 return getSelectedContact();
167 }
168 });
169 actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
170 Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
171 @Override
172 public boolean onAction() {
173 switchFormat();
174 return false;
175 }
176 });
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 });
197
198 return actions;
199 }
200
201 @Override
202 public DataType getDataType() {
203 return DataType.CARD;
204 }
205
206 @Override
207 public String getTitle() {
208 if (card != null) {
209 if (filter != null)
210 return card.getName() + " [" + filter + "]";
211 return card.getName();
212 }
213
214 return null;
215 }
216
217 @Override
218 protected List<TextPart> getLabel(int index, int width, boolean selected,
219 boolean focused) {
220 List<TextPart> parts = new LinkedList<TextPart>();
221
222 Contact contact = null;
223 if (index > -1 && index < contacts.size())
224 contact = contacts.get(index);
225
226 if (contact == null)
227 return parts;
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;
233 Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
234 : Element.CONTACT_LINE_DIRTY;
235
236 width -= 2; // dirty mark space
237
238 String[] array = contact.toStringArray(format, getSeparator(), " ",
239 width, UiColors.getInstance().isUnicode());
240
241 if (contact.isDirty()) {
242 parts.add(new TextPart(" ", el));
243 parts.add(new TextPart("*", elDirty));
244 } else {
245 parts.add(new TextPart(" ", elSep));
246 }
247
248 boolean separator = false;
249 for (String str : array) {
250 parts.add(new TextPart(str, (separator ? elSep : el)));
251 separator = !separator;
252 }
253
254 return parts;
255 }
256
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();
264 if (index > -1 && index < contacts.size())
265 return contacts.get(index);
266 return null;
267 }
268
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 }