001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.galleries.client.preview; 029 030import org.opencms.ade.galleries.client.preview.ui.CmsImagePreviewDialog; 031import org.opencms.ade.galleries.shared.CmsImageInfoBean; 032import org.opencms.gwt.client.CmsCoreProvider; 033import org.opencms.gwt.client.util.I_CmsSimpleCallback; 034 035import java.util.ArrayList; 036import java.util.HashMap; 037import java.util.List; 038import java.util.Map; 039 040import com.google.gwt.event.logical.shared.ValueChangeEvent; 041import com.google.gwt.event.logical.shared.ValueChangeHandler; 042 043/** 044 * Image preview dialog controller handler.<p> 045 * 046 * Delegates the actions of the preview controller to the preview dialog. 047 * 048 * @since 8.0.0 049 */ 050public class CmsImagePreviewHandler extends A_CmsPreviewHandler<CmsImageInfoBean> 051implements ValueChangeHandler<CmsCroppingParamBean> { 052 053 /** Enumeration of image tag attribute names. */ 054 public enum Attribute { 055 /** Image align attribute. */ 056 align, 057 /** Image alt attribute. */ 058 alt, 059 /** Image class attribute. */ 060 clazz, 061 /** Image copyright info. */ 062 copyright, 063 /** Image direction attribute. */ 064 dir, 065 /** No image selected if this attribute is present. */ 066 emptySelection, 067 /** The image hash. */ 068 hash, 069 /** Image height attribute. */ 070 height, 071 /** Image hspace attribute. */ 072 hspace, 073 /** Image id attribute. */ 074 id, 075 /** Image copyright flag. */ 076 insertCopyright, 077 /** Image link original flag. */ 078 insertLinkOrig, 079 /** Image spacing flag. */ 080 insertSpacing, 081 /** Image subtitle flag. */ 082 insertSubtitle, 083 /** Image language attribute. */ 084 lang, 085 /** Image link path. */ 086 linkPath, 087 /** Image link target. */ 088 linkTarget, 089 /** Image longDesc attribute. */ 090 longDesc, 091 /** Image style attribute. */ 092 style, 093 /** Image title attribute. */ 094 title, 095 /** Image vspace attribute. */ 096 vspace, 097 /** Image width attribute. */ 098 width 099 } 100 101 /** List of handlers for cropping changes. */ 102 private List<Runnable> m_croppingHandlers = new ArrayList<>(); 103 104 /** The cropping parameter. */ 105 private CmsCroppingParamBean m_croppingParam; 106 107 /** The image format handler. */ 108 private CmsImageFormatHandler m_formatHandler; 109 110 /** List of handlers for focal point changes. */ 111 private List<Runnable> m_imagePointHandlers = new ArrayList<>(); 112 113 /** The focal point controller. */ 114 private CmsFocalPointController m_pointController; 115 116 /** The preview dialog. */ 117 private CmsImagePreviewDialog m_previewDialog; 118 119 /** The image container width. */ 120 private int m_containerWidth; 121 122 /** The image container height. */ 123 private int m_containerHeight; 124 125 /** 126 * Constructor.<p> 127 * 128 * @param resourcePreview the resource preview instance 129 */ 130 public CmsImagePreviewHandler(CmsImageResourcePreview resourcePreview) { 131 132 super(resourcePreview); 133 m_previewDialog = resourcePreview.getPreviewDialog(); 134 m_pointController = new CmsFocalPointController( 135 () -> m_croppingParam, 136 this::getImageInfo, 137 this::onImagePointChanged); 138 } 139 140 /** 141 * Adds a handler for cropping changes.<p> 142 * 143 * @param action the handler to add 144 */ 145 public void addCroppingChangeHandler(Runnable action) { 146 147 m_croppingHandlers.add(action); 148 } 149 150 /** 151 * Adds a handler for focal point changes.<p> 152 * 153 * @param onImagePointChanged the handler to add 154 */ 155 public void addImagePointChangeHandler(Runnable onImagePointChanged) { 156 157 m_imagePointHandlers.add(onImagePointChanged); 158 } 159 160 /** 161 * Returns the image cropping parameter bean.<p> 162 * 163 * @return the image cropping parameter bean 164 */ 165 public CmsCroppingParamBean getCroppingParam() { 166 167 return m_croppingParam; 168 } 169 170 /** 171 * Gets the focal point controller.<p> 172 * 173 * @return the focal point controller 174 */ 175 public CmsFocalPointController getFocalPointController() { 176 177 return m_pointController; 178 } 179 180 /** 181 * Gets the format handler.<p> 182 * 183 * @return the format handler 184 */ 185 public CmsImageFormatHandler getFormatHandler() { 186 187 return m_formatHandler; 188 189 } 190 191 /** 192 * Returns the name of the currently selected image format.<p> 193 * 194 * @return the format name 195 */ 196 public String getFormatName() { 197 198 String result = ""; 199 if ((m_formatHandler != null) && (m_formatHandler.getCurrentFormat() != null)) { 200 result = m_formatHandler.getCurrentFormat().getName(); 201 } 202 return result; 203 } 204 205 /** 206 * Returns image tag attributes to set for editor plugins.<p> 207 * 208 * @param callback the callback to execute 209 */ 210 public void getImageAttributes(I_CmsSimpleCallback<Map<String, String>> callback) { 211 212 Map<String, String> result = new HashMap<String, String>(); 213 result.put(Attribute.hash.name(), String.valueOf(getImageIdHash())); 214 m_formatHandler.getImageAttributes(result); 215 m_previewDialog.getImageAttributes(result, callback); 216 } 217 218 /** 219 * Returns the structure id hash of the previewed image.<p> 220 * 221 * @return the structure id hash 222 */ 223 public int getImageIdHash() { 224 225 return m_resourceInfo.getHash(); 226 } 227 228 /** 229 * Gets the image information.<p> 230 * 231 * @return the image information 232 */ 233 public CmsImageInfoBean getImageInfo() { 234 235 return m_resourceInfo; 236 } 237 238 /** 239 * Returns the cropping parameter.<p> 240 * 241 * @param imageHeight the original image height 242 * @param imageWidth the original image width 243 * 244 * @return the cropping parameter 245 */ 246 public String getPreviewScaleParam(int imageHeight, int imageWidth) { 247 248 int maxHeight = m_containerHeight; 249 int maxWidth = m_containerWidth; 250 251 if ((m_croppingParam != null) && (m_croppingParam.isCropped() || m_croppingParam.isScaled())) { 252 // NOTE: getREstrictedSizeScaleParam does not work correctly if there isn't actually any cropping/scaling, so we explicitly don't use it in this case 253 return m_croppingParam.getRestrictedSizeScaleParam(maxHeight, maxWidth); 254 } 255 if ((imageHeight <= maxHeight) && (imageWidth <= maxWidth)) { 256 return ""; // dummy parameter, doesn't actually do anything 257 } 258 CmsCroppingParamBean restricted = new CmsCroppingParamBean(); 259 260 boolean tooHigh = imageHeight > maxHeight; 261 boolean tooWide = imageWidth > maxWidth; 262 double shrinkX = (1.0 * imageWidth) / maxWidth; 263 double shrinkY = (1.0 * imageHeight) / maxHeight; 264 double aspectRatio = (1.0 * imageWidth) / imageHeight; 265 if (tooHigh && tooWide) { 266 if (shrinkX > shrinkY) { 267 restricted.setTargetWidth(maxWidth); 268 restricted.setTargetHeight((int)(maxWidth / aspectRatio)); 269 } else { 270 restricted.setTargetHeight(maxHeight); 271 restricted.setTargetWidth((int)(maxHeight * aspectRatio)); 272 } 273 } else if (tooWide) { 274 restricted.setTargetWidth(maxWidth); 275 restricted.setTargetHeight((int)(maxWidth / aspectRatio)); 276 } else if (tooHigh) { 277 restricted.setTargetHeight(maxHeight); 278 restricted.setTargetWidth((int)(maxHeight * aspectRatio)); 279 } else { 280 restricted.setTargetWidth(imageWidth); 281 restricted.setTargetHeight(imageHeight); 282 } 283 return restricted.toString(); 284 } 285 286 /** 287 * @see com.google.gwt.event.logical.shared.ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent) 288 */ 289 public void onValueChange(ValueChangeEvent<CmsCroppingParamBean> event) { 290 291 m_croppingParam = event.getValue(); 292 String viewLink = m_resourcePreview.getViewLink(); 293 if (viewLink == null) { 294 viewLink = CmsCoreProvider.get().link(m_resourcePreview.getResourcePath()); 295 } 296 m_previewDialog.resetPreviewImage( 297 viewLink + "?" + getPreviewScaleParam(m_croppingParam.getOrgHeight(), m_croppingParam.getOrgWidth())); 298 onCroppingChanged(); 299 } 300 301 /** 302 * Sets the image format handler.<p> 303 * 304 * @param formatHandler the format handler 305 */ 306 public void setFormatHandler(CmsImageFormatHandler formatHandler) { 307 308 m_formatHandler = formatHandler; 309 m_croppingParam = m_formatHandler.getCroppingParam(); 310 m_formatHandler.addValueChangeHandler(this); 311 onCroppingChanged(); 312 } 313 314 /** 315 * 316 * Sets the dimensions of the area the image is going to be placed in. 317 * 318 * @param offsetWidth the container width 319 * @param offsetHeight the container height 320 */ 321 public void setImageContainerSize(int offsetWidth, int offsetHeight) { 322 323 m_containerWidth = offsetWidth; 324 m_containerHeight = offsetHeight; 325 } 326 327 /** 328 * Calls all cropping change handlers. 329 */ 330 private void onCroppingChanged() { 331 332 for (Runnable action : m_croppingHandlers) { 333 action.run(); 334 } 335 } 336 337 /** 338 * Calls all focal point change handlers.<p> 339 */ 340 private void onImagePointChanged() { 341 342 for (Runnable handler : m_imagePointHandlers) { 343 handler.run(); 344 } 345 346 } 347 348}