1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.admincentral.shellapp.favorites;
35
36 import info.magnolia.cms.i18n.MessagesUtil;
37 import info.magnolia.ui.admincentral.shellapp.favorites.EditingEvent.EditingListener;
38 import info.magnolia.ui.admincentral.shellapp.favorites.EditingEvent.EditingNotifier;
39 import info.magnolia.ui.api.overlay.ConfirmationCallback;
40 import info.magnolia.ui.api.shell.Shell;
41 import info.magnolia.ui.framework.AdmincentralNodeTypes;
42 import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter;
43 import info.magnolia.ui.vaadin.overlay.MessageStyleTypeEnum;
44
45 import org.apache.commons.lang.StringUtils;
46
47 import com.vaadin.event.FieldEvents.BlurEvent;
48 import com.vaadin.event.FieldEvents.BlurListener;
49 import com.vaadin.event.FieldEvents.FocusEvent;
50 import com.vaadin.event.FieldEvents.FocusListener;
51 import com.vaadin.event.LayoutEvents.LayoutClickEvent;
52 import com.vaadin.event.LayoutEvents.LayoutClickListener;
53 import com.vaadin.event.ShortcutListener;
54 import com.vaadin.shared.ui.label.ContentMode;
55 import com.vaadin.ui.Button.ClickEvent;
56 import com.vaadin.ui.Button.ClickListener;
57 import com.vaadin.ui.CustomComponent;
58 import com.vaadin.ui.HorizontalLayout;
59 import com.vaadin.ui.Label;
60 import com.vaadin.ui.NativeButton;
61 import com.vaadin.ui.TextField;
62
63
64
65
66 public final class FavoritesEntry extends CustomComponent implements EditingNotifier {
67
68 private HorizontalLayout root = new HorizontalLayout();
69 private String location;
70 private String title;
71 private String group = null;
72 private String nodename;
73 private TextField titleField;
74 private NativeButton editButton;
75 private NativeButton removeButton;
76 private boolean editable;
77 private boolean selected;
78 private EnterKeyShortcutListener enterKeyShortcutListener;
79 private EscapeKeyShortcutListener escapeKeyShortcutListener;
80 private Shell shell;
81
82
83 public FavoritesEntry(final AbstractJcrNodeAdapter favorite, final FavoritesView.Listener listener, final Shell shell) {
84 super();
85 this.shell = shell;
86 construct(favorite, listener);
87 }
88
89 public String getRelPath() {
90 return StringUtils.isBlank(group) ? this.nodename : this.group + "/" + this.nodename;
91 }
92
93 public String getNodename() {
94 return this.nodename;
95 }
96
97 public void setGroup(String group) {
98 this.group = group;
99 }
100
101 public String getGroup() {
102 return this.group;
103 }
104
105
106
107
108 public void reset() {
109 setEditable(false);
110 setSelected(false);
111 }
112
113 private void setEditable(boolean editable) {
114 this.editable = editable;
115 String icon = "icon-tick";
116 if (editable) {
117 titleField.addStyleName("editable");
118 titleField.focus();
119 titleField.selectAll();
120 } else {
121 icon = "icon-edit";
122 titleField.removeStyleName("editable");
123
124 titleField.setValue(title);
125 }
126 titleField.setReadOnly(!editable);
127 editButton.setCaption("<span class=\"" + icon + "\"></span>");
128 fireEvent(new EditingEvent(this, editable));
129 }
130
131 private void setSelected(boolean selected) {
132 this.selected = selected;
133 if (selected) {
134 addStyleName("selected");
135 } else {
136 removeStyleName("selected");
137 }
138 titleField.setReadOnly(true);
139 editButton.setVisible(selected);
140 editButton.setCaption("<span class=\"icon-edit\"></span>");
141 removeButton.setVisible(selected);
142 }
143
144 private void construct(final AbstractJcrNodeAdapter favorite, final FavoritesView.Listener listener) {
145 addStyleName("favorites-entry");
146 setSizeUndefined();
147 root.setSizeUndefined();
148
149 this.enterKeyShortcutListener = new EnterKeyShortcutListener(listener);
150 this.escapeKeyShortcutListener = new EscapeKeyShortcutListener();
151
152 this.nodename = favorite.getNodeName();
153 this.location = favorite.getItemProperty(AdmincentralNodeTypes.Favorite.URL).getValue().toString();
154 this.title = favorite.getItemProperty(AdmincentralNodeTypes.Favorite.TITLE).getValue().toString();
155
156 String icon = "icon-app";
157 if (favorite.getItemProperty(AdmincentralNodeTypes.Favorite.ICON).getValue() != null) {
158 icon = favorite.getItemProperty(AdmincentralNodeTypes.Favorite.ICON).getValue().toString();
159 }
160
161 final Label iconLabel = new Label();
162 iconLabel.setValue("<span class=\"" + icon + "\"></span>");
163 iconLabel.setStyleName("icon");
164 iconLabel.setContentMode(ContentMode.HTML);
165 root.addComponent(iconLabel);
166
167
168 titleField = new TextField();
169 titleField.setValue(title);
170 titleField.setReadOnly(true);
171
172 titleField.addFocusListener(new FocusListener() {
173
174 @Override
175 public void focus(FocusEvent event) {
176 iconLabel.removeShortcutListener(enterKeyShortcutListener);
177 titleField.addShortcutListener(enterKeyShortcutListener);
178 titleField.addShortcutListener(escapeKeyShortcutListener);
179 }
180 });
181
182 titleField.addBlurListener(new BlurListener() {
183
184 @Override
185 public void blur(BlurEvent event) {
186 titleField.removeShortcutListener(enterKeyShortcutListener);
187 titleField.removeShortcutListener(escapeKeyShortcutListener);
188 }
189 });
190
191 root.addComponent(titleField);
192
193 editButton = new NativeButton();
194 editButton.setHtmlContentAllowed(true);
195 editButton.setCaption("<span class=\"icon-edit\"></span>");
196 editButton.addStyleName("favorite-action");
197 editButton.addClickListener(new ClickListener() {
198
199 @Override
200 public void buttonClick(ClickEvent event) {
201 if (selected && !editable) {
202 setEditable(true);
203 return;
204 }
205 doEditTitle(listener);
206 }
207 });
208 editButton.setVisible(false);
209 root.addComponent(editButton);
210
211 removeButton = new NativeButton();
212 removeButton.setHtmlContentAllowed(true);
213 removeButton.setCaption("<span class=\"icon-trash\"></span>");
214 removeButton.addStyleName("favorite-action");
215 removeButton.addClickListener(new ClickListener() {
216
217 @Override
218 public void buttonClick(ClickEvent event) {
219 shell.openConfirmation(MessageStyleTypeEnum.WARNING, MessagesUtil.get("confirmation.delete.title.generic"), MessagesUtil.get("confirmation.cannot.undo"), MessagesUtil.get("confirmation.delete.yes"), MessagesUtil.get("confirmation.no"), true, new ConfirmationCallback() {
220
221 @Override
222 public void onSuccess() {
223 listener.removeFavorite(getRelPath());
224 }
225
226 @Override
227 public void onCancel() {
228
229 }
230 });
231 }
232 });
233 removeButton.setVisible(false);
234 root.addComponent(removeButton);
235
236 root.addLayoutClickListener(new LayoutClickListener() {
237
238 @Override
239 public void layoutClick(LayoutClickEvent event) {
240
241 if (event.getClickedComponent() == titleField && !editable) {
242 if (event.isDoubleClick()) {
243
244
245
246 } else {
247 listener.goToLocation(location);
248 }
249 } else if (event.getClickedComponent() == iconLabel) {
250 setSelected(!selected);
251 setEditable(false);
252 if (selected) {
253 iconLabel.addShortcutListener(enterKeyShortcutListener);
254 }
255 }
256 }
257 });
258
259 setCompositionRoot(root);
260 }
261
262 @Override
263 public void addEditingListener(EditingListener listener) {
264 addListener("onEdit", EditingEvent.class, listener, EditingEvent.EDITING_METHOD);
265
266 }
267
268 @Override
269 public void removeEditingListener(EditingListener listener) {
270 removeListener(EditingEvent.class, listener, EditingEvent.EDITING_METHOD);
271 }
272
273 private void doEditTitle(final FavoritesView.Listener listener) {
274 if (StringUtils.isBlank(titleField.getValue())) {
275 shell.openNotification(MessageStyleTypeEnum.ERROR, true, MessagesUtil.get("favorites.title.required"));
276 return;
277 }
278
279 boolean titleHasChanged = !title.equals(titleField.getValue());
280 if (editable && titleHasChanged) {
281 listener.editFavorite(getRelPath(), titleField.getValue());
282 }
283 setEditable(false);
284 }
285
286 private class EnterKeyShortcutListener extends ShortcutListener {
287 private FavoritesView.Listener listener;
288
289 public EnterKeyShortcutListener(final FavoritesView.Listener listener) {
290 super("", KeyCode.ENTER, null);
291 this.listener = listener;
292 }
293
294 @Override
295 public void handleAction(Object sender, Object target) {
296 if (editable) {
297 doEditTitle(listener);
298 } else {
299 setEditable(true);
300 }
301 }
302 }
303
304 private class EscapeKeyShortcutListener extends ShortcutListener {
305
306 public EscapeKeyShortcutListener() {
307 super("", KeyCode.ESCAPE, null);
308 }
309
310 @Override
311 public void handleAction(Object sender, Object target) {
312 reset();
313 }
314 }
315 }