org.opencms.ade.galleries.client.preview.CmsImageFormatHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.opencms.ade.galleries.client.preview.CmsImageFormatHandler.java

Source

/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) Alkacon Software GmbH (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.Messages;
import org.opencms.ade.galleries.client.preview.ui.CmsCroppingDialog;
import org.opencms.ade.galleries.client.preview.ui.CmsImageFormatsForm;
import org.opencms.ade.galleries.shared.I_CmsGalleryProviderConstants.GalleryMode;
import org.opencms.gwt.client.util.CmsClientStringUtil;
import org.opencms.util.CmsStringUtil;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;

/**
 * Image format form handler.<p>
 * 
 * @since 8.0.0
 */
public class CmsImageFormatHandler implements HasValueChangeHandlers<CmsCroppingParamBean> {

    /** Default image formats. */
    private enum DefaultRestriction {
        big, free, original, small, user
    }

    /** Default format configuration. */
    private static final String[] DEFAULT_FORMAT_NAMES = {
            DefaultRestriction.original.name() + ":"
                    + Messages.get().key(Messages.GUI_IMAGE_ORIGINAL_FORMAT_LABEL_0),
            DefaultRestriction.user.name() + ":" + Messages.get().key(Messages.GUI_IMAGE_USER_FORMAT_LABEL_0),
            DefaultRestriction.free.name() + ":" + Messages.get().key(Messages.GUI_IMAGE_FREE_FORMAT_LABEL_0),
            DefaultRestriction.small.name() + ":" + Messages.get().key(Messages.GUI_IMAGE_SMALL_FORMAT_LABEL_0),
            DefaultRestriction.big.name() + ":" + Messages.get().key(Messages.GUI_IMAGE_BIG_FORMAT_LABEL_0) };

    /** Default format configuration. */
    private static final String[] DEFAULT_FORMAT_VALUES = { DefaultRestriction.original.name(),
            DefaultRestriction.user.name(), DefaultRestriction.free.name(), DefaultRestriction.small.name(),
            DefaultRestriction.big.name() };

    private CmsCroppingDialog m_croppingDialog;

    /** The current cropping parameter. */
    private CmsCroppingParamBean m_croppingParam;

    /** The current image format restriction. */
    private I_CmsFormatRestriction m_currentFormat;

    /** The event bus. */
    private SimpleEventBus m_eventBus;

    /** The format form. */
    private CmsImageFormatsForm m_formatForm;

    /** The format names and labels configuration. */
    private String[] m_formatNames;

    /** The map of available format restrictions. */
    private Map<String, I_CmsFormatRestriction> m_formats = Collections.emptyMap();

    /** The Format configuration. */
    private String[] m_formatValues;

    /** Flag to indicate the handler has been initialized. */
    private boolean m_initialized;

    /** The image height. */
    private int m_originalHeight = -1;

    /** The image width. */
    private int m_originalWidth = -1;

    /** Flag indicating if the height / width ratio is locked. */
    private boolean m_ratioLocked;

    /** Flag to indicate if image format may be changed. */
    private boolean m_useFormats;

    /** The user format key, if available. */
    private String m_userFormatKey;

    /**
     * Constructor.<p>
     * 
     * @param galleryMode the gallery mode
     * @param selectedPath the selected gallery path
     * @param imageHeight the image height
     * @param imageWidth the image width
     */
    public CmsImageFormatHandler(GalleryMode galleryMode, String selectedPath, int imageHeight, int imageWidth) {

        m_originalHeight = imageHeight;
        m_originalWidth = imageWidth;
        m_croppingParam = CmsCroppingParamBean.parseImagePath(selectedPath);
        m_croppingParam.setOrgHeight(imageHeight);
        m_croppingParam.setOrgWidth(imageWidth);
        m_ratioLocked = true;
        readFormatsConfig(galleryMode);
        if (m_useFormats) {
            generateFormats();
        }
    }

    /**
     * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
     */
    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<CmsCroppingParamBean> handler) {

        return addHandler(handler, ValueChangeEvent.getType());
    }

    /**
     * @see com.google.gwt.event.shared.HasHandlers#fireEvent(com.google.gwt.event.shared.GwtEvent)
     */
    public void fireEvent(GwtEvent<?> event) {

        ensureHandlers().fireEventFromSource(event, this);
    }

    /**
     * Returns the current cropping parameter.<p>
     * 
     * @return the current cropping parameter
     */
    public CmsCroppingParamBean getCroppingParam() {

        return m_croppingParam;
    }

    /**
     * Returns the current format.<p>
     *
     * @return the current format
     */
    public I_CmsFormatRestriction getCurrentFormat() {

        return m_currentFormat;
    }

    /**
     * Returns the formats.<p>
     *
     * @return the formats
     */
    public Map<String, I_CmsFormatRestriction> getFormats() {

        return m_formats;
    }

    /**
     * Adds necessary attributes to the map.<p>
     * 
     * @param attributes the attribute map
     * @return the attribute map
     */
    public Map<String, String> getImageAttributes(Map<String, String> attributes) {

        attributes.put("height", String.valueOf(m_croppingParam.getResultingHeight()));
        attributes.put("width", String.valueOf(m_croppingParam.getResultingWidth()));
        return attributes;
    }

    /**
     * Returns the original height.<p>
     *
     * @return the original height
     */
    public int getOriginalHeight() {

        return m_originalHeight;
    }

    /**
     * Returns the original width.<p>
     *
     * @return the original width
     */
    public int getOriginalWidth() {

        return m_originalWidth;
    }

    /**
     * Initializes the format form handler.<p>
     * 
     * @param formatForm the format form
     * @param croppingDialog the cropping dialog
     */
    public void init(CmsImageFormatsForm formatForm, CmsCroppingDialog croppingDialog) {

        m_croppingDialog = croppingDialog;
        m_formatForm = formatForm;
        if (m_useFormats) {
            for (Entry<String, I_CmsFormatRestriction> entry : m_formats.entrySet()) {
                m_formatForm.addFormatSelectOption(entry.getKey(), entry.getValue().getLabel());
            }
            I_CmsFormatRestriction match = getMatchingFormat(m_croppingParam, true);
            if (match != null) {
                m_currentFormat = match;
                m_formatForm.setFormatSelectValue(match.getName());
                adjustToCurrentFormat();
            } else {
                onResetSize();
            }
        } else {
            m_formatForm.addFormatSelectOption("--", "--");
            m_formatForm.setFormEnabled(m_useFormats);
        }
        if (m_croppingParam.isCropped()) {
            setCropping(m_croppingParam);
        }
        m_croppingDialog.addValueChangeHandler(new ValueChangeHandler<CmsCroppingParamBean>() {

            /**
             * Executed on value change. Sets the returned cropping parameters.<p>
             * 
             * @param event the value change event
             */
            public void onValueChange(ValueChangeEvent<CmsCroppingParamBean> event) {

                setCropping(event.getValue());
            }
        });
        m_initialized = true;
    }

    /**
     * Returns if scaling formats may be selected for the image.<p>
     * 
     * @return <code>true</code> if scaling formats may be selected for the image
     */
    public boolean isUseFormats() {

        return m_useFormats;
    }

    /**
     * Execute on format change.<p>
     * 
     * @param formatKey the new format value
     */
    public void onFormatChange(String formatKey) {

        // setting the selected format restriction
        m_currentFormat = m_formats.get(formatKey);
        m_currentFormat.adjustCroppingParam(m_croppingParam);
        adjustToCurrentFormat();
        if (m_initialized) {
            // fire change only if initialized
            fireValueChangedEvent();
        }
    }

    /**
     * Execute on height change.<p>
     * 
     * @param height the new height
     */
    public void onHeightChange(String height) {

        int value = CmsClientStringUtil.parseInt(height);
        if ((m_croppingParam.getTargetHeight() == value) || (value == 0)) {
            // the value has not changed, ignore'0'
            return;
        }
        m_croppingParam.setTargetHeight(value);
        if (m_ratioLocked) {
            m_croppingParam.setTargetWidth((value * m_originalWidth) / m_originalHeight);
            m_formatForm.setWidthInput(m_croppingParam.getTargetWidth());
        }
        if (!m_currentFormat.isHeightEditable() && hasUserFormatRestriction()) {
            m_formatForm.setFormatSelectValue(m_userFormatKey);
        } else {
            fireValueChangedEvent();
        }
    }

    /**
     * Execute when the lock image ratio is clicked.<p>
     * 
     * @param locked <code>true</code> if ratio is locked
     */
    public void onLockRatio(boolean locked) {

        m_ratioLocked = locked;
    }

    /**
     * Execute when cropping is removed.<p>
     */
    public void onRemoveCropping() {

        m_formatForm.setCropped(false);
        onResetSize();
    }

    /**
     * Execute to reset image format and size input.<p>
     */
    public void onResetSize() {

        String restrictionKey;
        if (m_formats.containsKey(DefaultRestriction.original.name())) {
            restrictionKey = DefaultRestriction.original.name();
        } else {
            restrictionKey = m_formats.keySet().iterator().next();
        }
        m_formatForm.setFormatSelectValue(restrictionKey);
        m_croppingParam.reset();
        onFormatChange(restrictionKey);
    }

    /**
     * Execute on width change.<p>
     * 
     * @param width the new width
     */
    public void onWidthChange(String width) {

        int value = CmsClientStringUtil.parseInt(width);
        if ((m_croppingParam.getTargetWidth() == value) || (value == 0)) {
            // the value has not changed, ignore'0'
            return;
        }
        m_croppingParam.setTargetWidth(value);
        if (m_ratioLocked) {
            m_croppingParam.setTargetHeight((value * m_originalHeight) / m_originalWidth);
            m_formatForm.setHeightInput(m_croppingParam.getTargetHeight());
        }
        if (!m_currentFormat.isWidthEditable() && hasUserFormatRestriction()) {
            m_formatForm.setFormatSelectValue(m_userFormatKey);
        } else {
            fireValueChangedEvent();
        }
    }

    /**
     * Shows the image cropping dialog.<p>
     */
    public void openCropping() {

        CmsCroppingParamBean param = new CmsCroppingParamBean(m_croppingParam);
        m_currentFormat.adjustCroppingParam(param);
        m_croppingDialog.show(param);
    }

    /**
     * Sets the given cropping parameter.<p>
     * 
     * @param croppingParam the cropping parameter
     */
    public void setCropping(CmsCroppingParamBean croppingParam) {

        m_croppingParam = croppingParam;
        m_formatForm.setHeightInput(m_croppingParam.getTargetHeight());
        m_formatForm.setWidthInput(m_croppingParam.getTargetWidth());

        // only in case of the original-format-restriction, the cropping dialog may be opened to override the selected format
        if (m_currentFormat instanceof CmsOriginalFormatRestriction) {
            I_CmsFormatRestriction format = getMatchingFormat(m_croppingParam, false);
            if (format != null) {
                m_currentFormat = format;
                m_formatForm.setFormatSelectValue(format.getName());
            }
        }
        m_formatForm.setCropped(true);
        fireValueChangedEvent();
    }

    /**
     * Sets the original width.<p>
     *
     * @param originalWidth the original width to set
     */
    public void setOriginalWidth(int originalWidth) {

        m_originalWidth = originalWidth;
    }

    /**
     * Adds this handler to the widget.
     * 
     * @param <H> the type of handler to add
     * @param type the event type
     * @param handler the handler
     * @return {@link HandlerRegistration} used to remove the handler
     */
    protected final <H extends EventHandler> HandlerRegistration addHandler(final H handler,
            GwtEvent.Type<H> type) {

        return ensureHandlers().addHandlerToSource(type, this, handler);
    }

    /** 
     * Helper method for firing a 'value changed' event.<p>
     */
    protected void fireValueChangedEvent() {

        ValueChangeEvent.fire(this, m_croppingParam);
    }

    /**
     * Lazy initializing the handler manager.<p>
     * 
     * @return the handler manager
     */
    private SimpleEventBus ensureHandlers() {

        if (m_eventBus == null) {
            m_eventBus = new SimpleEventBus();
        }
        return m_eventBus;
    }

    /**
     * Generates the format restriction objects.<p>
     */
    private void generateFormats() {

        m_formats = new LinkedHashMap<String, I_CmsFormatRestriction>();
        for (int i = 0; i < m_formatValues.length; i++) {
            String value = m_formatValues[i].trim();

            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(value)) {
                String label = value;
                String key = value;
                if ((m_formatNames != null) && (m_formatNames.length > i)
                        && CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_formatNames[i])) {
                    int pos = m_formatNames[i].indexOf(":");
                    if (pos > 0) {
                        label = m_formatNames[i].substring(pos + 1, m_formatNames[i].length());
                        key = m_formatNames[i].substring(0, pos);
                    } else {
                        label = m_formatNames[i];
                        key = m_formatNames[i];
                    }
                }

                DefaultRestriction restrictionType = null;
                try {
                    restrictionType = DefaultRestriction.valueOf(value);
                } catch (Exception e) {
                    // happens with user defined restriction settings
                }
                if (restrictionType != null) {
                    switch (restrictionType) {
                    case original:
                        m_formats.put(key, new CmsOriginalFormatRestriction(key, label));
                        break;
                    case user:
                        m_userFormatKey = key;
                        m_formats.put(key, new CmsUserFormatRestriction(key, label));
                        break;
                    case free:
                        m_formats.put(key, new CmsFreeFormatRestriction(key, label));
                        break;
                    case small:
                        m_formats.put(key, new CmsImageFormatRestriction(key, label, "200x?"));
                        break;
                    case big:
                        m_formats.put(key, new CmsImageFormatRestriction(key, label, "500x?"));
                        break;
                    default:
                    }
                } else {
                    if (CmsImageFormatRestriction.isValidConfig(value)) {
                        m_formats.put(key, new CmsImageFormatRestriction(key, label, value));
                    }
                }
            }
        }
    }

    /**
     * Checks the format restrictions if the match the giving cropping parameter.<p>
     * 
     * @param croppingParam the cropping parameter
     * @param forceByName force format match by name within cropping parameter
     * 
     * @return the matching format restriction
     */
    private I_CmsFormatRestriction getMatchingFormat(CmsCroppingParamBean croppingParam, boolean forceByName) {

        I_CmsFormatRestriction result = null;
        if (forceByName && m_formats.containsKey(croppingParam.getFormatName())) {
            result = m_formats.get(croppingParam.getFormatName());
            if (!result.matchesCroppingParam(croppingParam)) {
                result.adjustCroppingParam(croppingParam);
            }
            return result;
        }
        for (I_CmsFormatRestriction format : m_formats.values()) {

            if (format.matchesCroppingParam(croppingParam)) {
                result = format;
                if (format.getName().equals(croppingParam.getFormatName())) {
                    break;
                }
            }
        }
        return result;
    }

    /**
     * Returns if the user defined format restriction is available.<p>
     * 
     * @return <code>true</code> if the user defined format restriction is available
     */
    private boolean hasUserFormatRestriction() {

        return m_userFormatKey != null;
    }

    /**
     * Reads the format configuration for the given gallery mode.<p>
     * 
     * @param mode the gallery mode
     */
    private void readFormatsConfig(GalleryMode mode) {

        switch (mode) {
        case editor:
            m_useFormats = true;
            m_formatNames = DEFAULT_FORMAT_NAMES;
            m_formatValues = DEFAULT_FORMAT_VALUES;
            break;
        case widget:
            m_useFormats = CmsPreviewUtil.isShowFormats();
            if (m_useFormats) {
                m_formatValues = CmsPreviewUtil.getFormats();
                if (m_formatValues == null) {
                    m_formatNames = DEFAULT_FORMAT_NAMES;
                    m_formatValues = DEFAULT_FORMAT_VALUES;
                } else {
                    m_formatNames = CmsPreviewUtil.getFormatNames();
                }
            }
            break;
        case ade:
        case view:
            m_useFormats = false;
            break;
        default:
        }
    }

    private void adjustToCurrentFormat() {

        // in case of a locked or fixed image ratio height and width need to be reset
        int height = m_croppingParam.getOrgHeight();
        int width = m_croppingParam.getOrgWidth();
        if (m_croppingParam.isScaled()) {
            if (m_croppingParam.getTargetHeight() == -1) {
                height = (int) Math.floor(((1.00 * m_croppingParam.getOrgHeight()) / m_croppingParam.getOrgWidth())
                        * m_croppingParam.getTargetWidth());
            } else {
                height = m_croppingParam.getTargetHeight();
            }
            if (m_croppingParam.getTargetWidth() == -1) {
                width = (int) Math.floor(((1.00 * m_croppingParam.getOrgWidth()) / m_croppingParam.getOrgHeight())
                        * m_croppingParam.getTargetHeight());
            } else {
                width = m_croppingParam.getTargetWidth();
            }

        }
        m_formatForm.setHeightInput(height);
        m_formatForm.setWidthInput(width);
        // enabling/disabling ratio lock button
        if (m_currentFormat.isFixedRatio()) {
            m_formatForm.setRatioButton(false, false,
                    Messages.get().key(Messages.GUI_PRIVIEW_BUTTON_RATIO_FIXED_0));
            m_ratioLocked = true;
        } else {
            if (!m_currentFormat.isHeightEditable() && !m_currentFormat.isWidthEditable()) {
                // neither height nor width are editable, disable ratio lock button
                m_formatForm.setRatioButton(false, false,
                        Messages.get().key(Messages.GUI_PRIVIEW_BUTTON_NOT_EDITABLE_0));
            } else {
                m_formatForm.setRatioButton(false, true, null);
            }
            m_ratioLocked = true;
        }
        // enabling/disabling height and width input
        m_formatForm.setHeightInputEnabled(m_currentFormat.isHeightEditable() || hasUserFormatRestriction());
        m_formatForm.setWidthInputEnabled(m_currentFormat.isWidthEditable() || hasUserFormatRestriction());
    }
}