Show some information in ContacTView (FN/N, email, phone, notes)
[jvcard.git] / src / be / nikiroo / jvcard / tui / panes / ContactDetails.java
1 package be.nikiroo.jvcard.tui.panes;
2
3 import java.awt.Image;
4 import java.util.Base64;
5 import java.util.LinkedList;
6 import java.util.List;
7
8 import javax.swing.ImageIcon;
9
10 import be.nikiroo.jvcard.Contact;
11 import be.nikiroo.jvcard.Data;
12 import be.nikiroo.jvcard.TypeInfo;
13 import be.nikiroo.jvcard.i18n.Trans;
14 import be.nikiroo.jvcard.tui.ImageTextControl;
15 import be.nikiroo.jvcard.tui.KeyAction;
16 import be.nikiroo.jvcard.tui.KeyAction.DataType;
17 import be.nikiroo.jvcard.tui.KeyAction.Mode;
18 import be.nikiroo.jvcard.tui.UiColors;
19
20 import com.googlecode.lanterna.TerminalSize;
21 import com.googlecode.lanterna.gui2.BorderLayout;
22 import com.googlecode.lanterna.gui2.Direction;
23 import com.googlecode.lanterna.gui2.Label;
24 import com.googlecode.lanterna.gui2.LinearLayout;
25 import com.googlecode.lanterna.gui2.Panel;
26 import com.googlecode.lanterna.input.KeyType;
27
28 public class ContactDetails extends MainContent {
29 private Contact contact;
30 private Panel top;
31 private ImageTextControl txtImage;
32 private Image image;
33 private boolean fullscreenImage;
34 private Panel infoPanel;
35 private Label note;
36
37 public ContactDetails(Contact contact) {
38 BorderLayout blayout = new BorderLayout();
39 setLayoutManager(blayout);
40
41 top = new Panel();
42 blayout = new BorderLayout();
43 top.setLayoutManager(blayout);
44
45 infoPanel = new Panel();
46 infoPanel.setLayoutManager(new LinearLayout(Direction.VERTICAL));
47 top.addComponent(infoPanel, BorderLayout.Location.CENTER);
48
49 Panel notePanel = new Panel();
50 notePanel.setLayoutManager(new LinearLayout(Direction.HORIZONTAL));
51
52 notePanel.addComponent(UiColors.Element.VIEW_CONTACT_NOTES_TITLE
53 .createLabel("Notes:"));
54 note = UiColors.Element.VIEW_CONTACT_NORMAL.createLabel("");
55 notePanel.addComponent(note);
56
57 setContact(contact);
58
59 addComponent(top, BorderLayout.Location.TOP);
60 addComponent(notePanel, BorderLayout.Location.CENTER);
61 }
62
63 /**
64 * Change the enclosed {@link Contact} from this {@link ContactDetails}.
65 *
66 * @param contact
67 * the new {@link Contact}
68 */
69 public void setContact(Contact contact) {
70 if (this.contact == contact)
71 return;
72
73 this.contact = contact;
74
75 if (contact == null) {
76 image = null;
77 } else {
78 infoPanel.removeAllComponents();
79
80 String name = contact.getPreferredDataValue("FN");
81 if (name == null || name.length() == 0) {
82 // TODO format it ourself
83 name = contact.getPreferredDataValue("N");
84 }
85
86 // TODO: i18n + do it properly
87 infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NAME
88 .createLabel(name));
89
90 infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
91 .createLabel(""));
92 infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
93 .createLabel("Phone: "
94 + contact.getPreferredDataValue("TEL")));
95 infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
96 .createLabel("eMail: "
97 + contact.getPreferredDataValue("EMAIL")));
98 infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
99 .createLabel(""));
100
101 String notes = contact.getPreferredDataValue("NOTE");
102 if (notes == null)
103 notes = "";
104 note.setText(notes.replaceAll("\\\\n", "\n"));
105
106 Data photo = contact.getPreferredData("PHOTO");
107 if (photo != null) {
108 TypeInfo encoding = null;
109 TypeInfo type = null;
110 for (int index = 0; index < photo.size(); index++) {
111 TypeInfo info = photo.get(index);
112 if (info.getName() != null) {
113 if (info.getName().equalsIgnoreCase("ENCODING"))
114 encoding = info;
115 if (info.getName().equalsIgnoreCase("TYPE"))
116 type = info;
117 }
118 }
119
120 if (encoding != null && encoding.getValue() != null
121 && encoding.getValue().equalsIgnoreCase("b")) {
122
123 image = new ImageIcon(Base64.getDecoder().decode(
124 photo.getValue())).getImage();
125 }
126 }
127 }
128
129 setImage(image);
130 }
131
132 @Override
133 public DataType getDataType() {
134 return DataType.DATA;
135 }
136
137 @Override
138 public List<KeyAction> getKeyBindings() {
139 List<KeyAction> actions = new LinkedList<KeyAction>();
140
141 // TODO
142 actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
143 Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
144 @Override
145 public boolean onAction() {
146 if (txtImage != null) {
147 txtImage.switchMode();
148 }
149
150 return false;
151 }
152 });
153 actions.add(new KeyAction(Mode.NONE, 'i',
154 Trans.StringId.KEY_ACTION_INVERT) {
155 @Override
156 public boolean onAction() {
157 if (txtImage != null) {
158 txtImage.invertColor();
159 }
160
161 return false;
162 }
163 });
164 actions.add(new KeyAction(Mode.NONE, 'f',
165 Trans.StringId.KEY_ACTION_FULLSCREEN) {
166 @Override
167 public boolean onAction() {
168 fullscreenImage = !fullscreenImage;
169 setImage(image);
170 return false;
171 }
172 });
173
174 return actions;
175 }
176
177 @Override
178 public synchronized Panel setSize(TerminalSize size) {
179 super.setSize(size);
180 setImage(image);
181 return this;
182 }
183
184 /**
185 * Set the {@link Image} to render and refresh it to the current size
186 * constraints.
187 *
188 * @param image
189 * the new {@link Image}
190 */
191 private void setImage(Image image) {
192 this.image = image;
193
194 if (txtImage != null && top.containsComponent(txtImage))
195 top.removeComponent(txtImage);
196
197 TerminalSize size = getTxtSize();
198 if (size != null) {
199 if (txtImage != null)
200 txtImage.setSize(size);
201 else
202 txtImage = new ImageTextControl(image, size);
203 }
204
205 if (size != null) {
206 top.addComponent(txtImage, BorderLayout.Location.LEFT);
207 }
208
209 invalidate();
210 }
211
212 /**
213 * Compute the size to use for the {@link Image} text rendering. Return NULL
214 * in case of error.
215 *
216 * @return the {@link TerminalSize} to use or NULL if it is not possible
217 */
218 private TerminalSize getTxtSize() {
219 if (image != null && getSize() != null && getSize().getColumns() > 0
220 && getSize().getRows() > 0) {
221 if (fullscreenImage) {
222 return getSize();
223 } else {
224 // TODO: configure size?
225 int w = getSize().getColumns() - 40;
226 int h = getSize().getRows() - 5;
227 if (w <= 0 || h <= 0)
228 return null;
229
230 return new TerminalSize(w, h);
231 }
232 }
233
234 return null;
235 }
236 }