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