All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.ade.galleries.client.preview.CmsFocalPointController Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

The newest version!
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.ade.galleries.client.preview;

import org.opencms.ade.galleries.client.preview.ui.CmsFocalPoint;
import org.opencms.ade.galleries.client.preview.util.CmsBoxFit;
import org.opencms.ade.galleries.client.preview.util.CmsCompositeTransform;
import org.opencms.ade.galleries.client.preview.util.CmsRectangle;
import org.opencms.ade.galleries.client.preview.util.CmsTranslate;
import org.opencms.ade.galleries.client.preview.util.I_CmsTransform;
import org.opencms.ade.galleries.shared.CmsImageInfoBean;
import org.opencms.ade.galleries.shared.CmsPoint;
import org.opencms.gwt.client.CmsCoreProvider;
import org.opencms.gwt.client.rpc.CmsRpcAction;
import org.opencms.gwt.client.util.CmsClientStringUtil;
import org.opencms.gwt.shared.CmsGwtConstants;
import org.opencms.gwt.shared.property.CmsPropertyChangeSet;
import org.opencms.gwt.shared.property.CmsPropertyModification;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;

/**
 * Handles manipulation of the focal point in the gallery dialog.

*/ public class CmsFocalPointController { /** Global static flag to enable / disable focal point modification. */ public static final boolean ENABLED = true; /** Preview handler registration for the event handler used for drag / drop. */ private static HandlerRegistration m_previewRegistration; /** The container. */ private FlowPanel m_container; /** The transformation for transforming from the image parent's coordinate system to the true underlying image's native coordinate system. */ private CmsCompositeTransform m_coordinateTransform; /** The source of the cropping parameter information. */ private Supplier m_croppingProvider; /** The current focal point location. */ private CmsPoint m_focalPoint; /** The currently displayed image. */ private Image m_image; /** The source of the image information. */ private Supplier m_imageInfoProvider; /** The action to execute when the focal point is changed. */ private Runnable m_nextAction; /** The widget representing the focal point. */ private CmsFocalPoint m_pointWidget; /** The region in which the user should be able to move the focal point widget on the screen. */ private CmsRectangle m_region; /** The focal point location which was last saved. */ private CmsPoint m_savedFocalPoint; /** * Creates a new instance.

* * @param croppingProvider the source of the cropping information * @param infoProvider the source of the image info * @param nextAction the action to execute when the focal point is changed */ public CmsFocalPointController( Supplier croppingProvider, Supplier infoProvider, Runnable nextAction) { m_croppingProvider = croppingProvider; m_imageInfoProvider = infoProvider; m_nextAction = nextAction; } /** * Clears the static event handler for the drag and drop.

*/ private static void clearEventHandler() { if (m_previewRegistration != null) { m_previewRegistration.removeHandler(); } m_previewRegistration = null; } /** * Gets the pageX offset for a mouse event.

* * @param event the event * * @return the pageX offset */ private static native double pageX(NativeEvent event) /*-{ return event.pageX; }-*/; /** * Gets the pageY offset for a mouse event.

* * @param event the event * * @return the pageY offset */ private static native double pageY(NativeEvent event) /*-{ return event.pageY; }-*/; /** * Transforms a rectangle with the inverse of a coordinate transform.

* * @param transform the coordinate transform * @param region the rectangle to transform * @return the transformed rectangle */ private static CmsRectangle transformRegionBack(I_CmsTransform transform, CmsRectangle region) { CmsPoint topLeft = region.getTopLeft(); CmsPoint bottomRight = region.getBottomRight(); return CmsRectangle.fromPoints(transform.transformBack(topLeft), transform.transformBack(bottomRight)); } /** * Called when the user clicks on the focal point widget.

* * This starts drag and drop. */ public void onStartDrag() { if (ENABLED && isEditable()) { registerEventHandler(); } } /** * Saves the focal point to a property on the image.

*/ public void reset() { if (isEditable()) { String val = ""; CmsUUID sid = m_imageInfoProvider.get().getStructureId(); List propChanges = new ArrayList<>(); propChanges.add(new CmsPropertyModification(sid, CmsGwtConstants.PROPERTY_IMAGE_FOCALPOINT, val, false)); propChanges.add(new CmsPropertyModification(sid, CmsGwtConstants.PROPERTY_IMAGE_FOCALPOINT, val, true)); final CmsPropertyChangeSet changeSet = new CmsPropertyChangeSet(sid, propChanges); CmsRpcAction action = new CmsRpcAction() { @Override public void execute() { CmsCoreProvider.getVfsService().saveProperties(changeSet, false, this); } @SuppressWarnings("synthetic-access") @Override protected void onResponse(Void result) { m_focalPoint = null; m_savedFocalPoint = null; m_imageInfoProvider.get().setFocalPoint(null); updatePoint(); if (m_nextAction != null) { m_nextAction.run(); } } }; action.execute(); } } /** * Updates the image.

* * @param container the parent widget for the image * @param previewImage the image */ public void updateImage(FlowPanel container, Image previewImage) { if (!ENABLED) { return; } String path = m_imageInfoProvider.get().getResourcePath(); if (CmsClientStringUtil.checkIsPathOrLinkToSvg(path)) { return; } m_image = previewImage; clearImagePoint(); m_savedFocalPoint = m_imageInfoProvider.get().getFocalPoint(); m_focalPoint = m_savedFocalPoint; m_container = container; previewImage.addLoadHandler(new LoadHandler() { @SuppressWarnings("synthetic-access") public void onLoad(LoadEvent event) { updateScaling(); updatePoint(); } }); } /** * Removes the focal point widget.

*/ private void clearImagePoint() { if (m_pointWidget != null) { m_pointWidget.removeFromParent(); m_pointWidget = null; } } /** * Gets the point which is the center of the crop region, or the center of the original image if it isn't cropped, in the image's coordinate system.

* * @return the center point of the crop region */ private CmsPoint getCropCenter() { CmsCroppingParamBean crop = m_croppingProvider.get(); CmsImageInfoBean info = m_imageInfoProvider.get(); if ((crop == null) || !crop.isCropped()) { return new CmsPoint(info.getWidth() / 2, info.getHeight() / 2); } else { return new CmsPoint( crop.getCropX() + (crop.getCropWidth() / 2), crop.getCropY() + (crop.getCropHeight() / 2)); } } /** * Gets the rectangle in the image's coordinate system which corresponds to the crop region (or the whole image, * in case cropping is not used).

* * @return the crop region */ private CmsRectangle getNativeCropRegion() { CmsCroppingParamBean crop = m_croppingProvider.get(); CmsImageInfoBean info = m_imageInfoProvider.get(); if ((crop == null) || !crop.isCropped()) { return CmsRectangle.fromLeftTopWidthHeight(0, 0, info.getWidth(), info.getHeight()); } else { return CmsRectangle.fromLeftTopWidthHeight( crop.getCropX(), crop.getCropY(), crop.getCropWidth(), crop.getCropHeight()); } } /** * Handles mouse drag.

* * @param nativeEvent the mousemove event */ private void handleMove(NativeEvent nativeEvent) { Element imageElem = m_image.getElement(); int offsetX = ((int)pageX(nativeEvent)) - imageElem.getParentElement().getAbsoluteLeft(); int offsetY = ((int)pageY(nativeEvent)) - imageElem.getParentElement().getAbsoluteTop(); if (m_coordinateTransform != null) { CmsPoint screenPoint = new CmsPoint(offsetX, offsetY); screenPoint = m_region.constrain(screenPoint); // make sure we remain in the screen region corresponding to original image (or crop). m_pointWidget.setCenterCoordsRelativeToParent((int)screenPoint.getX(), (int)screenPoint.getY()); CmsPoint logicalPoint = m_coordinateTransform.transformForward(screenPoint); m_focalPoint = logicalPoint; } } /** * Check if the image is editable.

* * @return true if the image is editable */ private boolean isEditable() { String noEditReason = m_imageInfoProvider.get().getNoEditReason(); boolean result = CmsStringUtil.isEmptyOrWhitespaceOnly(noEditReason); return result; } /** * Registers the preview event handler used for drag and drop.

*/ private void registerEventHandler() { clearEventHandler(); m_previewRegistration = Event.addNativePreviewHandler(new NativePreviewHandler() { @SuppressWarnings("synthetic-access") public void onPreviewNativeEvent(NativePreviewEvent event) { if (!(m_pointWidget.isAttached())) { clearEventHandler(); return; } NativeEvent nativeEvent = event.getNativeEvent(); if (nativeEvent == null) { return; } int eventType = event.getTypeInt(); switch (eventType) { case Event.ONMOUSEUP: clearEventHandler(); save(); break; case Event.ONMOUSEMOVE: handleMove(nativeEvent); break; default: break; } } }); } /** * Saves the focal point to a property on the image.

*/ private void save() { if ((m_focalPoint != null) && isEditable()) { int x = (int)m_focalPoint.getX(); int y = (int)m_focalPoint.getY(); String val = "" + x + "," + y; CmsUUID sid = m_imageInfoProvider.get().getStructureId(); List propChanges = new ArrayList<>(); propChanges.add(new CmsPropertyModification(sid, CmsGwtConstants.PROPERTY_IMAGE_FOCALPOINT, val, false)); final CmsPropertyChangeSet changeSet = new CmsPropertyChangeSet(sid, propChanges); CmsRpcAction action = new CmsRpcAction() { @Override public void execute() { CmsCoreProvider.getVfsService().saveProperties(changeSet, false, this); } @SuppressWarnings("synthetic-access") @Override protected void onResponse(Void result) { m_savedFocalPoint = m_focalPoint; if (m_pointWidget != null) { m_pointWidget.setIsDefault(false); } m_imageInfoProvider.get().setFocalPoint(m_focalPoint); if (m_nextAction != null) { m_nextAction.run(); } } }; action.execute(); } } /** * Updates the focal point widget.

*/ private void updatePoint() { clearImagePoint(); CmsPoint nativePoint; if (m_focalPoint == null) { CmsPoint cropCenter = getCropCenter(); nativePoint = cropCenter; } else if (!getNativeCropRegion().contains(m_focalPoint)) { return; } else { nativePoint = m_focalPoint; } m_pointWidget = new CmsFocalPoint(CmsFocalPointController.this); boolean isDefault = m_savedFocalPoint == null; m_pointWidget.setIsDefault(isDefault); m_container.add(m_pointWidget); CmsPoint screenPoint = m_coordinateTransform.transformBack(nativePoint); m_pointWidget.setCenterCoordsRelativeToParent((int)screenPoint.getX(), (int)screenPoint.getY()); } /** * Sets up the coordinate transformations between the coordinate system of the parent element of the image element and the native coordinate system * of the original image. */ private void updateScaling() { List transforms = new ArrayList<>(); CmsCroppingParamBean crop = m_croppingProvider.get(); CmsImageInfoBean info = m_imageInfoProvider.get(); double wv = m_image.getElement().getParentElement().getOffsetWidth(); double hv = m_image.getElement().getParentElement().getOffsetHeight(); if (crop == null) { transforms.add( new CmsBoxFit(CmsBoxFit.Mode.scaleOnlyIfNecessary, wv, hv, info.getWidth(), info.getHeight())); } else { int wt, ht; wt = crop.getTargetWidth() >= 0 ? crop.getTargetWidth() : info.getWidth(); ht = crop.getTargetHeight() >= 0 ? crop.getTargetHeight() : info.getHeight(); transforms.add(new CmsBoxFit(CmsBoxFit.Mode.scaleOnlyIfNecessary, wv, hv, wt, ht)); if (crop.isCropped()) { transforms.add( new CmsBoxFit(CmsBoxFit.Mode.scaleAlways, wt, ht, crop.getCropWidth(), crop.getCropHeight())); transforms.add(new CmsTranslate(crop.getCropX(), crop.getCropY())); } else { transforms.add( new CmsBoxFit(CmsBoxFit.Mode.scaleAlways, wt, ht, crop.getOrgWidth(), crop.getOrgHeight())); } } CmsCompositeTransform chain = new CmsCompositeTransform(transforms); m_coordinateTransform = chain; if ((crop == null) || !crop.isCropped()) { m_region = transformRegionBack( m_coordinateTransform, CmsRectangle.fromLeftTopWidthHeight(0, 0, info.getWidth(), info.getHeight())); } else { m_region = transformRegionBack( m_coordinateTransform, CmsRectangle.fromLeftTopWidthHeight( crop.getCropX(), crop.getCropY(), crop.getCropWidth(), crop.getCropHeight())); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy