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.api.overlay.ConfirmationCallback;
38 import info.magnolia.ui.framework.AdmincentralNodeTypes;
39 import info.magnolia.ui.api.shell.Shell;
40 import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter;
41 import info.magnolia.ui.vaadin.overlay.MessageStyleTypeEnum;
42
43 import java.util.Iterator;
44 import java.util.Map;
45 import java.util.SortedSet;
46 import java.util.TreeSet;
47
48 import org.apache.commons.lang.StringUtils;
49
50 import com.vaadin.event.FieldEvents.BlurEvent;
51 import com.vaadin.event.FieldEvents.BlurListener;
52 import com.vaadin.event.FieldEvents.FocusEvent;
53 import com.vaadin.event.FieldEvents.FocusListener;
54 import com.vaadin.event.LayoutEvents.LayoutClickEvent;
55 import com.vaadin.event.LayoutEvents.LayoutClickListener;
56 import com.vaadin.event.ShortcutListener;
57 import com.vaadin.ui.Button.ClickEvent;
58 import com.vaadin.ui.Button.ClickListener;
59 import com.vaadin.ui.Component;
60 import com.vaadin.ui.CssLayout;
61 import com.vaadin.ui.NativeButton;
62 import com.vaadin.ui.TextField;
63
64
65
66
67 public final class FavoritesGroup extends CssLayout {
68
69 private TextField titleField;
70 private NativeButton editButton;
71 private NativeButton removeButton;
72 private String title;
73 private String relPath;
74 private boolean editable;
75 private boolean selected;
76 private CssLayout wrapper;
77 private EnterKeyShortcutListener enterKeyShortcutListener;
78 private EscapeKeyShortcutListener escapeKeyShortcutListener;
79 private Shell shell;
80
81
82
83
84 public FavoritesGroup() {
85 addStyleName("no-group");
86 }
87
88 public FavoritesGroup(final AbstractJcrNodeAdapter favoritesGroup, final FavoritesView.Listener listener, final Shell shell) {
89 this.shell = shell;
90
91 addStyleName("favorites-group");
92 construct(favoritesGroup, listener);
93
94 final Map<String, AbstractJcrNodeAdapter> nodeAdapters = favoritesGroup.getChildren();
95 final SortedSet<String> keys = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
96 keys.addAll(nodeAdapters.keySet());
97
98 for (String key : keys) {
99 final AbstractJcrNodeAdapter fav = nodeAdapters.get(key);
100 final FavoritesEntry favEntry = new FavoritesEntry(fav, listener, shell);
101 addComponent(favEntry);
102 }
103 }
104
105
106
107
108 public void reset() {
109
110 if (titleField != null) {
111 setEditable(false);
112 setSelected(false);
113 }
114 Iterator<Component> components = getComponentIterator();
115 while (components.hasNext()) {
116 Component component = components.next();
117 if(component instanceof FavoritesEntry) {
118 FavoritesEntry fav = (FavoritesEntry) component;
119 fav.reset();
120 }
121 }
122 }
123
124 private void setEditable(boolean editable) {
125 this.editable = editable;
126 String icon = "icon-tick";
127 if (editable) {
128 titleField.addStyleName("editable");
129 titleField.focus();
130 titleField.selectAll();
131 } else {
132 icon = "icon-edit";
133
134 titleField.setValue(title);
135 titleField.removeStyleName("editable");
136 }
137 titleField.setReadOnly(!editable);
138 editButton.setCaption("<span class=\"" + icon + "\"></span>");
139 }
140
141 private void setSelected(boolean selected) {
142 this.selected = selected;
143 if (selected) {
144 wrapper.addStyleName("selected");
145 } else {
146 wrapper.removeStyleName("selected");
147 }
148 titleField.setReadOnly(true);
149 editButton.setVisible(selected);
150 editButton.setCaption("<span class=\"icon-edit\"></span>");
151 removeButton.setVisible(selected);
152 }
153
154 private void construct(final AbstractJcrNodeAdapter favoritesGroup, final FavoritesView.Listener listener) {
155 wrapper = new CssLayout();
156 wrapper.addStyleName("favorites-group-title");
157
158 this.enterKeyShortcutListener = new EnterKeyShortcutListener(listener);
159 this.escapeKeyShortcutListener = new EscapeKeyShortcutListener();
160
161 this.relPath = favoritesGroup.getNodeName();
162 this.title = favoritesGroup.getItemProperty(AdmincentralNodeTypes.Favorite.TITLE).getValue().toString();
163
164 titleField = new TextField();
165 titleField.setValue(title);
166 titleField.setReadOnly(true);
167 titleField.addFocusListener(new FocusListener() {
168
169 @Override
170 public void focus(FocusEvent event) {
171 titleField.addShortcutListener(enterKeyShortcutListener);
172 titleField.addShortcutListener(escapeKeyShortcutListener);
173 }
174 });
175
176 titleField.addBlurListener(new BlurListener() {
177
178 @Override
179 public void blur(BlurEvent event) {
180 titleField.removeShortcutListener(enterKeyShortcutListener);
181 titleField.removeShortcutListener(escapeKeyShortcutListener);
182 }
183 });
184
185 wrapper.addComponent(titleField);
186
187 editButton = new NativeButton();
188 editButton.setHtmlContentAllowed(true);
189 editButton.setCaption("<span class=\"icon-edit\"></span>");
190 editButton.addStyleName("favorite-action");
191 editButton.addClickListener(new ClickListener() {
192
193 @Override
194 public void buttonClick(ClickEvent event) {
195 if (selected && !editable) {
196 setEditable(true);
197 return;
198 }
199 doEditTitle(listener);
200 }
201 });
202 editButton.setVisible(false);
203 wrapper.addComponent(editButton);
204
205 removeButton = new NativeButton();
206 removeButton.setHtmlContentAllowed(true);
207 removeButton.setCaption("<span class=\"icon-trash\"></span>");
208 removeButton.addStyleName("favorite-action");
209 removeButton.addClickListener(new ClickListener() {
210
211 @Override
212 public void buttonClick(ClickEvent event) {
213 shell.openConfirmation(MessageStyleTypeEnum.WARNING, MessagesUtil.get("favorites.group.confirmation.title"), MessagesUtil.get("confirmation.cannot.undo"), MessagesUtil.get("confirmation.delete.yes"), MessagesUtil.get("confirmation.no"), true, new ConfirmationCallback() {
214
215 @Override
216 public void onSuccess() {
217 listener.removeGroup(relPath);
218 }
219
220 @Override
221 public void onCancel() {
222
223 }
224 });
225 }
226 });
227 removeButton.setVisible(false);
228 wrapper.addComponent(removeButton);
229
230 addLayoutClickListener(new LayoutClickListener() {
231
232 @Override
233 public void layoutClick(LayoutClickEvent event) {
234
235 if (event.getClickedComponent() == titleField) {
236 if (!editable) {
237 setSelected(!selected);
238 }
239 }
240 }
241 });
242
243 addComponent(wrapper);
244 }
245
246 private void doEditTitle(final FavoritesView.Listener listener) {
247 if (StringUtils.isBlank(titleField.getValue())) {
248 shell.openNotification(MessageStyleTypeEnum.ERROR, true, MessagesUtil.get("favorites.title.required"));
249 return;
250 }
251 boolean titleHasChanged = !title.equals(titleField.getValue());
252 if (editable && titleHasChanged) {
253 listener.editGroup(relPath, titleField.getValue());
254 }
255 setEditable(false);
256 }
257
258 private class EnterKeyShortcutListener extends ShortcutListener {
259 private FavoritesView.Listener listener;
260
261 public EnterKeyShortcutListener(final FavoritesView.Listener listener) {
262 super("", KeyCode.ENTER, null);
263 this.listener = listener;
264 }
265
266 @Override
267 public void handleAction(Object sender, Object target) {
268 if (editable) {
269 doEditTitle(listener);
270 } else {
271 setEditable(true);
272 }
273 }
274 }
275
276 private class EscapeKeyShortcutListener extends ShortcutListener {
277
278 public EscapeKeyShortcutListener() {
279 super("", KeyCode.ESCAPE, null);
280 }
281
282 @Override
283 public void handleAction(Object sender, Object target) {
284 reset();
285 }
286 }
287 }