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