View Javadoc
1   /**
2    * This file Copyright (c) 2020 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.dam.app.field.link;
35  
36  import info.magnolia.dam.api.Asset;
37  import info.magnolia.dam.api.Item;
38  import info.magnolia.dam.app.data.AssetPropertySetFactory;
39  import info.magnolia.dam.app.imageprovider.AssetPreviewProvider;
40  import info.magnolia.i18nsystem.SimpleTranslator;
41  import info.magnolia.icons.MagnoliaIcons;
42  import info.magnolia.ui.preview.AbstractItemPreviewComponent;
43  import info.magnolia.ui.theme.ResurfaceTheme;
44  
45  import java.io.ByteArrayInputStream;
46  import java.io.IOException;
47  import java.io.InputStream;
48  import java.util.HashMap;
49  import java.util.Map;
50  
51  import javax.inject.Inject;
52  
53  import org.apache.commons.io.IOUtils;
54  import org.slf4j.Logger;
55  import org.slf4j.LoggerFactory;
56  
57  import com.google.common.net.MediaType;
58  import com.vaadin.event.MouseEvents;
59  import com.vaadin.server.Resource;
60  import com.vaadin.server.StreamResource;
61  import com.vaadin.ui.Button;
62  import com.vaadin.ui.Component;
63  import com.vaadin.ui.CssLayout;
64  import com.vaadin.ui.Image;
65  import com.vaadin.ui.Label;
66  import com.vaadin.ui.Layout;
67  import com.vaadin.ui.Notification;
68  import com.vaadin.ui.UI;
69  import com.vaadin.ui.VerticalLayout;
70  import com.vaadin.ui.Window;
71  
72  /**
73   * ItemPreviewComponent for Dam Item.
74   */
75  public class DamItemPreviewComponent extends AbstractItemPreviewComponent<Item> {
76  
77      private static final Logger log = LoggerFactory.getLogger(DamItemPreviewComponent.class);
78  
79      @Inject
80      public DamItemPreviewComponent(SimpleTranslator i18n, AssetPropertySetFactory propertySetFactory, AssetPreviewProvider previewProvider) {
81          super(i18n, propertySetFactory, previewProvider, getProperties());
82          this.setVisible(false);
83      }
84  
85      private static Map<String, Class> getProperties() {
86          Map<String, Class> properties = new HashMap<>();
87          properties.put("name", String.class);
88          properties.put("fileSize", String.class);
89          properties.put("mimeType", String.class);
90          return properties;
91      }
92  
93      @Override
94      protected Layout getRootLayout() {
95          return rootLayout == null ? new VerticalLayout() : rootLayout;
96      }
97  
98      @Override
99      protected Component createDetailComponent(String propertyName, Object value) {
100         Label detailComponent = new Label();
101         detailComponent.setCaption(getI18n().translate("dam.damLinkField.fileInfo.".concat(propertyName)));
102         detailComponent.setValue(String.valueOf(value));
103         return detailComponent;
104     }
105 
106     @Override
107     public void onValueChange(Item item) {
108         if (item != null && item.isAsset()) {
109             super.onValueChange(item);
110         } else {
111             clearRootLayout();
112         }
113     }
114 
115     @Override
116     protected Component refreshItemPreview(Item item) {
117         if (!item.isAsset()) {
118             return null;
119         }
120         MediaType type = getAssetMediaType((Asset) item);
121         Image defaultThumbnail = new Image("");
122         defaultThumbnail.setIcon(MagnoliaIcons.FILE);
123 
124         Component image = type.is(MediaType.ANY_IMAGE_TYPE) ? super.refreshItemPreview(item) : defaultThumbnail;
125 
126         this.setVisible(true);
127         CssLayout previewLayout = new CssLayout();
128         previewLayout.setSizeFull();
129         previewLayout.addStyleName("link-file-panel");
130 
131         CssLayout controlButtonPanel = new CssLayout();
132         controlButtonPanel.addStyleName("control-button-panel");
133         controlButtonPanel.setWidth(30, Unit.PIXELS);
134 
135         if (type.is(MediaType.ANY_IMAGE_TYPE)) {
136 
137             previewLayout.removeStyleName("link-file-panel");
138             previewLayout.addStyleName("link-file-panel-large");
139 
140             Button openLightBoxViewBtn = createControlPanelButton(MagnoliaIcons.SEARCH);
141             openLightBoxViewBtn.addClickListener(event -> openLightBoxView((Asset) item));
142             openLightBoxViewBtn.setDescription(getI18n().translate("dam.damUploadField.lightbox"));
143             controlButtonPanel.addComponents(openLightBoxViewBtn);
144         }
145         image.addStyleName("file-preview-thumbnail");
146 
147         previewLayout.addComponents(controlButtonPanel, image);
148 
149         return previewLayout;
150     }
151 
152     private MediaType getAssetMediaType(Asset item) {
153         String mimeType = item.getMimeType();
154         try {
155             return MediaType.parse(mimeType);
156         } catch (Exception e) {
157             log.error("Cannot parse asset item mime type", e);
158             return null;
159         }
160     }
161 
162     private Button createControlPanelButton(Resource icon) {
163         Button button = new Button(icon);
164         button.addStyleNames(ResurfaceTheme.BUTTON_ICON, "control-button");
165         return button;
166     }
167 
168     void openLightBoxView(Asset item) {
169         try (
170                 InputStream contentStream = item.getContentStream();
171                 ByteArrayInputStream inputStream = new ByteArrayInputStream(IOUtils.toByteArray(contentStream))
172         ) {
173             StreamResource.StreamSource streamSource = () -> inputStream;
174             StreamResource streamResource = new StreamResource(streamSource, "");
175 
176             CssLayout imageComponent = new CssLayout(new Image("", streamResource));
177             imageComponent.setSizeFull();
178             imageComponent.setStyleName("light-box-content");
179 
180             Window window = new Window();
181             window.addStyleName("light-box");
182             window.setDraggable(false);
183             window.setResizable(false);
184             window.setModal(true);
185             window.setContent(imageComponent);
186             window.center();
187 
188             UI.getCurrent().addWindow(window);
189 
190             window.addClickListener((MouseEvents.ClickListener) event -> window.close());
191         } catch (IOException e) {
192             Notification.show(getI18n().translate("dam.damUploadField.lightbox.error.subject"),
193                     getI18n().translate("dam.damUploadField.lightbox.error.message"),
194                     Notification.Type.ERROR_MESSAGE);
195             log.error("Could not open asset content stream.", e);
196         }
197     }
198 }