View Javadoc

1   /**
2    * This file Copyright (c) 2013-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.admincentral.shellapp.favorites;
35  
36  import info.magnolia.i18nsystem.SimpleTranslator;
37  import info.magnolia.ui.admincentral.shellapp.favorites.EditingEvent.EditingListener;
38  import info.magnolia.ui.admincentral.shellapp.favorites.SelectedEvent.SelectedListener;
39  import info.magnolia.ui.api.shell.Shell;
40  import info.magnolia.ui.framework.AdmincentralNodeTypes;
41  import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter;
42  import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
43  import info.magnolia.ui.vaadin.splitfeed.SplitFeed;
44  
45  import java.util.Map;
46  
47  import javax.inject.Inject;
48  
49  import com.vaadin.event.LayoutEvents.LayoutClickEvent;
50  import com.vaadin.event.LayoutEvents.LayoutClickListener;
51  import com.vaadin.event.dd.DragAndDropEvent;
52  import com.vaadin.event.dd.DropHandler;
53  import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
54  import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
55  import com.vaadin.shared.ui.label.ContentMode;
56  import com.vaadin.ui.Component;
57  import com.vaadin.ui.CustomComponent;
58  import com.vaadin.ui.DragAndDropWrapper;
59  import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
60  import com.vaadin.ui.Label;
61  import com.vaadin.ui.VerticalLayout;
62  
63  /**
64   * Default view implementation for favorites.
65   */
66  public final class FavoritesViewImpl extends CustomComponent implements FavoritesView {
67  
68      private VerticalLayout layout = new VerticalLayout();
69      private FavoritesView.Listener listener;
70      private FavoritesGroup noGroup;
71      private FavoritesForm favoriteForm;
72      private Shell shell;
73      private SplitFeed splitPanel = new SplitFeed();
74      private Label emptyPlaceHolder = new Label();
75      private Component currentlySelectedFavoriteItem;
76      private final SimpleTranslator i18n;
77  
78      @Override
79      public String getId() {
80          return "favorite";
81      }
82  
83      @Inject
84      public FavoritesViewImpl(Shell shell, FavoritesManager favoritesManager, SimpleTranslator i18n) {
85          super();
86          this.shell = shell;
87          this.i18n = i18n;
88          construct();
89      }
90  
91      @Override
92      public void setListener(FavoritesView.Listener listener) {
93          this.listener = listener;
94      }
95  
96      private void construct() {
97          layout.addStyleName("favorites");
98          layout.setHeight("100%");
99          layout.setWidth("900px");
100 
101         emptyPlaceHolder.addStyleName("emptyplaceholder");
102         emptyPlaceHolder.setContentMode(ContentMode.HTML);
103         emptyPlaceHolder.setValue(String.format("<span class=\"icon-favorites\"></span><div class=\"message\">%s</div>", i18n.translate("favorites.empty")));
104 
105         splitPanel.setVisible(false);
106 
107         layout.addLayoutClickListener(new LayoutClickListener() {
108 
109             @Override
110             public void layoutClick(LayoutClickEvent event) {
111                 Component clickedComponent = event.getClickedComponent();
112                 reset(clickedComponent);
113             }
114         });
115 
116         layout.addComponent(emptyPlaceHolder);
117         layout.addComponent(splitPanel);
118         layout.setExpandRatio(splitPanel, 0);
119         // Disable the hints
120         layout.addStyleName("no-vertical-drag-hints");
121         layout.addStyleName("no-horizontal-drag-hints");
122         // layout.addStyleName("no-box-drag-hints");
123     }
124 
125     @Override
126     public Component asVaadinComponent() {
127         return layout;
128     }
129 
130     @Override
131     public void setFavoriteLocation(JcrNewNodeAdapter newFavorite, JcrNewNodeAdapter newGroup, Map<String, String> availableGroupsNames) {
132         layout.removeComponent(favoriteForm);
133         favoriteForm = new FavoritesForm(newFavorite, newGroup, availableGroupsNames, listener, shell, i18n);
134         layout.addComponent(favoriteForm);
135     }
136 
137     @Override
138     public void init(AbstractJcrNodeAdapter favorites, JcrNewNodeAdapter favoriteSuggestion, JcrNewNodeAdapter groupSuggestion, Map<String, String> availableGroups) {
139 
140         final Map<String, AbstractJcrNodeAdapter> nodeAdapters = favorites.getChildren();
141 
142         if (nodeAdapters.isEmpty()) {
143             emptyPlaceHolder.setVisible(true);
144             splitPanel.setVisible(false);
145             layout.setExpandRatio(splitPanel, 0);
146             layout.setExpandRatio(emptyPlaceHolder, 1);
147         } else {
148             emptyPlaceHolder.setVisible(false);
149             splitPanel.setVisible(true);
150             layout.setExpandRatio(splitPanel, 1);
151             layout.setExpandRatio(emptyPlaceHolder, 0);
152 
153             noGroup = new FavoritesGroup(i18n);
154             splitPanel.getLeftContainer().removeAllComponents();
155             splitPanel.getRightContainer().removeAllComponents();
156             for (String key : nodeAdapters.keySet()) {
157                 final AbstractJcrNodeAdapter favoriteAdapter = nodeAdapters.get(key);
158                 if (AdmincentralNodeTypes.Favorite.NAME.equals(favoriteAdapter.getPrimaryNodeTypeName())) {
159                     final FavoritesEntry favEntry = new FavoritesEntry(favoriteAdapter, listener, shell, i18n);
160                     final EntryDragAndDropWrapper wrapper = new EntryDragAndDropWrapper(favEntry, listener);
161                     favEntry.addEditingListener(new EditingListener() {
162 
163                         @Override
164                         public void onEdit(EditingEvent event) {
165                             if (event.isEditing()) {
166                                 wrapper.setDragStartMode(DragStartMode.NONE);
167                             } else {
168                                 wrapper.setDragStartMode(DragStartMode.WRAPPER);
169                             }
170                         }
171                     });
172                     favEntry.addSelectedListener(new SelectedListener() {
173 
174                         @Override
175                         public void onSelected(SelectedEvent event) {
176                             updateSelection(event.getComponent());
177                         }
178                     });
179                     noGroup.addComponent(wrapper);
180                 } else {
181                     FavoritesGroup group = new FavoritesGroup(favoriteAdapter, listener, shell, this, i18n);
182                     group.addSelectedListener(new SelectedListener() {
183 
184                         @Override
185                         public void onSelected(SelectedEvent event) {
186                             updateSelection(event.getComponent());
187                         }
188                     });
189                     splitPanel.getRightContainer().addComponent(group);
190                 }
191             }
192             DragAndDropWrapper nogroupWrap = new DragAndDropWrapper(noGroup);
193             noGroup.setSizeFull();
194             nogroupWrap.setSizeFull();
195 
196             nogroupWrap.setDropHandler(new DropHandler() {
197 
198                 @Override
199                 public void drop(DragAndDropEvent event) {
200                     Component wrappedComponent = ((EntryDragAndDropWrapper) event.getTransferable().getSourceComponent()).getWrappedComponent();
201                     String sourcePath = ((FavoritesEntry) wrappedComponent).getRelPath();
202                     listener.moveFavorite(sourcePath, null);
203                 }
204 
205                 @Override
206                 public AcceptCriterion getAcceptCriterion() {
207 
208                     return new ServerSideCriterion() {
209 
210                         @Override
211                         public boolean accept(DragAndDropEvent dragEvent) {
212                             // accept only entries, not groups
213                             AbstractFavoritesDragAndDropWrapper wrapper = (AbstractFavoritesDragAndDropWrapper) dragEvent.getTransferable().getSourceComponent();
214                             if (!(wrapper.getWrappedComponent() instanceof FavoritesEntry)) {
215                                 return false;
216                             }
217 
218                             // drop location: can drop anywhere in the target zone.
219                             return true;
220                         }
221                     };
222                 }
223 
224             });
225             splitPanel.getLeftContainer().addComponent(nogroupWrap);
226         }
227 
228         if (favoriteForm != null) {
229             layout.removeComponent(favoriteForm);
230         }
231         favoriteForm = new FavoritesForm(favoriteSuggestion, groupSuggestion, availableGroups, listener, shell, i18n);
232         layout.addComponent(favoriteForm);
233     }
234 
235     /**
236      * Clicking outside a group or favorite resets everything.
237      */
238     private void reset(Component clickedComponent) {
239         if (!(clickedComponent instanceof SplitFeed.FeedSection)) {
240             return;
241         }
242         favoriteForm.close();
243         if (currentlySelectedFavoriteItem instanceof FavoritesEntry) {
244             ((FavoritesEntry) currentlySelectedFavoriteItem).reset();
245         } else if (currentlySelectedFavoriteItem instanceof FavoritesGroup) {
246             ((FavoritesGroup) currentlySelectedFavoriteItem).reset();
247         }
248         currentlySelectedFavoriteItem = null;
249     }
250 
251     @Override
252     public void updateSelection(final Component newSelection) {
253         if (newSelection == currentlySelectedFavoriteItem) {
254             return;
255         }
256         if (currentlySelectedFavoriteItem instanceof FavoritesEntry) {
257             ((FavoritesEntry) currentlySelectedFavoriteItem).reset();
258         } else if (currentlySelectedFavoriteItem instanceof FavoritesGroup) {
259             ((FavoritesGroup) currentlySelectedFavoriteItem).reset();
260         }
261         currentlySelectedFavoriteItem = newSelection;
262     }
263 }