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

org.opencms.acacia.client.ui.CmsInlineEntityWidget 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.

There is a newer version: 18.0
Show newest version
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (C) Alkacon Software (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.acacia.client.ui;

import org.opencms.acacia.client.CmsAttributeHandler;
import org.opencms.acacia.client.CmsButtonBarHandler;
import org.opencms.acacia.client.CmsChoiceMenuEntryBean;
import org.opencms.acacia.client.CmsEditorBase;
import org.opencms.acacia.client.I_CmsInlineFormParent;
import org.opencms.acacia.client.I_CmsInlineHtmlUpdateHandler;
import org.opencms.acacia.client.I_CmsWidgetService;
import org.opencms.acacia.client.css.I_CmsLayoutBundle;
import org.opencms.acacia.client.entity.CmsEntityBackend;
import org.opencms.acacia.shared.CmsEntity;
import org.opencms.acacia.shared.CmsType;
import org.opencms.gwt.client.ui.CmsHighlightingBorder;
import org.opencms.gwt.client.ui.CmsPopup;
import org.opencms.gwt.client.ui.CmsPushButton;
import org.opencms.gwt.client.ui.I_CmsButton;
import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
import org.opencms.gwt.client.util.CmsPositionBean;

import java.util.List;

import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Widget allowing form based editing for parts of a content to enhance the in-line editing.

*/ public final class CmsInlineEntityWidget extends Composite { /** * Flow panel with handling descendant resizes to reposition pop-up.

*/ protected class FormPanel extends FlowPanel implements org.opencms.gwt.client.I_CmsDescendantResizeHandler { /** * Constructor.

*/ protected FormPanel() { } /** * @see org.opencms.gwt.client.I_CmsDescendantResizeHandler#onResizeDescendant() */ public void onResizeDescendant() { positionPopup(); } } /** * Timer to update the HTML.

*/ protected class UpdateTimer extends Timer { /** Indicates if the timer is scheduled. */ private boolean m_scheduled; /** * @see com.google.gwt.user.client.Timer#cancel() */ @Override public void cancel() { m_scheduled = false; super.cancel(); } /** * Returns if the timer is already scheduled.

* * @return true if the timer is scheduled */ public boolean isScheduled() { return m_scheduled; } /** * @see com.google.gwt.user.client.Timer#run() */ @Override public void run() { m_scheduled = false; runHtmlUpdate(); } /** * @see com.google.gwt.user.client.Timer#schedule(int) */ @Override public void schedule(int delayMillis) { m_scheduled = true; super.schedule(delayMillis); } } /** * The UI binder interface.

*/ interface I_InlineEntityWidgetUiBinder extends UiBinder { // nothing to do } /** The UI binder instance. */ private static I_InlineEntityWidgetUiBinder uiBinder = GWT.create(I_InlineEntityWidgetUiBinder.class); /** The add button. */ @UiField protected CmsAttributeChoiceWidget m_addButton; /** The attribute choice button. */ @UiField protected CmsAttributeChoiceWidget m_attributeChoice; /** The down button. */ @UiField protected CmsPushButton m_downButton; /** The injected button. */ @UiField protected CmsPushButton m_editButton; /** The remove button. */ @UiField protected CmsPushButton m_removeButton; /** The up button. */ @UiField protected CmsPushButton m_upButton; /** The highlighting border widget. */ CmsHighlightingBorder m_highlighting; /** The pop-up panel. */ CmsPopup m_popup; /** The handler of the attribute to edit. */ private CmsAttributeHandler m_attributeHandler; /** The attribute value index. */ private int m_attributeIndex; /** The change handler registration. */ private HandlerRegistration m_entityChangeHandlerRegistration; /** The parent widget. */ private I_CmsInlineFormParent m_formParent; /** Indicates if the content has been changed while the edit pop-up was shown. */ private boolean m_hasChanges; /** Handles HTML updates if required. */ private I_CmsInlineHtmlUpdateHandler m_htmlUpdateHandler; /** A timer to update the overlay position. */ private Timer m_overlayTimer; /** The parent of the entity to edit. */ private CmsEntity m_parentEntity; /** Flag indicating the popup has been closed. */ private boolean m_popupClosed; /** The reference DOM element, will be highlighted during editing. */ private Element m_referenceElement; /** Flag indicating it is required to open the edit popup aftera HTML update. */ private boolean m_requireShowPopup; /** Flag indicating an HTML update is running. */ private boolean m_runningUpdate; /** The dialog title. */ private String m_title; /** Schedules the HTML update. */ private UpdateTimer m_updateTimer; /** The widget service. */ private I_CmsWidgetService m_widgetService; /** * Constructor.

* * @param referenceElement the reference DOM element, will be highlighted during editing * @param formParent the parent widget * @param parentEntity the parent of the entity to edit * @param attributeHandler the attribute handler * @param attributeIndex the attribute value index * @param htmlUpdateHandler handles HTML updates if required * @param widgetService the widget service */ private CmsInlineEntityWidget( Element referenceElement, I_CmsInlineFormParent formParent, CmsEntity parentEntity, CmsAttributeHandler attributeHandler, int attributeIndex, I_CmsInlineHtmlUpdateHandler htmlUpdateHandler, I_CmsWidgetService widgetService) { initWidget(uiBinder.createAndBindUi(this)); m_parentEntity = parentEntity; m_attributeHandler = attributeHandler; m_attributeIndex = attributeIndex; m_referenceElement = referenceElement; m_formParent = formParent; m_htmlUpdateHandler = htmlUpdateHandler; m_widgetService = widgetService; m_title = ""; m_updateTimer = new UpdateTimer(); m_popupClosed = true; initButtons(); addDomHandler(CmsButtonBarHandler.INSTANCE, MouseOverEvent.getType()); addDomHandler(CmsButtonBarHandler.INSTANCE, MouseOutEvent.getType()); } /** * Creates the inline edit widget and injects it next to the context element.

* * @param element the context element * @param formParent the parent widget * @param parentEntity the parent entity * @param attributeHandler the attribute handler * @param attributeIndex the attribute value index * @param htmlUpdateHandler handles HTML updates if required * @param widgetService the widget service * * @return the widget instance */ public static CmsInlineEntityWidget createWidgetForEntity( Element element, I_CmsInlineFormParent formParent, CmsEntity parentEntity, CmsAttributeHandler attributeHandler, int attributeIndex, I_CmsInlineHtmlUpdateHandler htmlUpdateHandler, I_CmsWidgetService widgetService) { CmsInlineEntityWidget widget = new CmsInlineEntityWidget( element, formParent, parentEntity, attributeHandler, attributeIndex, htmlUpdateHandler, widgetService); CmsInlineEditOverlay.getRootOverlay().addButton(widget, element.getAbsoluteTop()); attributeHandler.updateButtonVisibilty(widget); return widget; } /** * Returns the attribute value index.

* * @return the attribute value index */ public int getAttributeIndex() { return m_attributeIndex; } /** * Sets the visibility of the reference element highlighting border.

* * @param visible true to show the highlighting */ public void setContentHighlightingVisible(boolean visible) { if (visible) { if (m_highlighting == null) { m_highlighting = new CmsHighlightingBorder( CmsPositionBean.getBoundingClientRect(m_referenceElement), CmsHighlightingBorder.BorderColor.red); RootPanel.get().add(m_highlighting); } else { m_highlighting.setPosition(CmsPositionBean.getBoundingClientRect(m_referenceElement)); } } else { if (m_highlighting != null) { m_highlighting.removeFromParent(); m_highlighting = null; } } } /** * Updates the visibility of the add, remove, up and down buttons.

* * @param hasEditButton true if the edit button should be visible * @param hasAddButton true if the add button should be visible * @param hasRemoveButton true if the remove button should be visible * @param hasSortButtons true if the sort buttons should be visible */ public void updateButtonVisibility( boolean hasEditButton, boolean hasAddButton, boolean hasRemoveButton, boolean hasSortButtons) { if (hasEditButton) { m_editButton.getElement().getStyle().clearDisplay(); } else { m_editButton.getElement().getStyle().setDisplay(Display.NONE); } // if (hasAddButton && m_isChoice) { // m_attributeChoice.getElement().getStyle().clearDisplay(); // } else { m_attributeChoice.getElement().getStyle().setDisplay(Display.NONE); // } if (hasAddButton) { m_addButton.getElement().getStyle().clearDisplay(); } else { m_addButton.getElement().getStyle().setDisplay(Display.NONE); } if (hasRemoveButton) { m_removeButton.getElement().getStyle().clearDisplay(); } else { m_removeButton.getElement().getStyle().setDisplay(Display.NONE); } if (hasSortButtons && (m_attributeIndex != 0)) { m_upButton.getElement().getStyle().clearDisplay(); } else { m_upButton.getElement().getStyle().setDisplay(Display.NONE); } if (hasSortButtons && (getElement().getNextSibling() != null)) { m_downButton.getElement().getStyle().clearDisplay(); } else { m_downButton.getElement().getStyle().setDisplay(Display.NONE); } if (hasEditButton && (hasAddButton || hasRemoveButton || hasSortButtons)) { // set multi button mode addStyleName(I_CmsLayoutBundle.INSTANCE.form().multiButtonBar()); } else { removeStyleName(I_CmsLayoutBundle.INSTANCE.form().multiButtonBar()); } } /** * Positions the widget button above the reference element.

*/ protected void positionWidget() { CmsInlineEditOverlay.getRootOverlay().setButtonPosition(this, m_referenceElement.getAbsoluteTop()); } /** Adds a new attribute value. */ void addNewAttributeValue() { m_attributeHandler.addNewAttributeValueToEntity(m_attributeIndex); m_requireShowPopup = true; m_attributeIndex += 1; runHtmlUpdate(); } /** * Repositions the edit overlay after the HTML has been updated.

*/ void afterHtmlUpdate() { if (m_overlayTimer != null) { m_overlayTimer.cancel(); m_overlayTimer = null; } m_runningUpdate = false; List elements = CmsEntityBackend.getInstance().getAttributeElements( m_parentEntity, m_attributeHandler.getAttributeName(), m_formParent.getElement()); if (m_popupClosed) { // the form popup has already been closed, reinitialize the editing widgets for updated HTML CmsInlineEditOverlay.updateCurrentOverlayPosition(); if (m_requireShowPopup) { if (elements.size() > m_attributeIndex) { m_referenceElement = elements.get(m_attributeIndex); } showEditPopup(null); m_hasChanges = true; } else { CmsInlineEditOverlay.getRootOverlay().clearButtonPanel(); m_htmlUpdateHandler.reinitWidgets(m_formParent); } } else { if (m_referenceElement != null) { CmsInlineEditOverlay.removeLastOverlay(); } if (elements.size() > m_attributeIndex) { m_referenceElement = elements.get(m_attributeIndex); CmsInlineEditOverlay.addOverlayForElement(m_referenceElement); } else { m_referenceElement = m_formParent.getElement(); CmsInlineEditOverlay.addOverlayForElement(m_referenceElement); } } // schedule to update the ovelay position m_overlayTimer = new Timer() { /** Timer run counter. */ private int m_timerRuns; /** * @see com.google.gwt.user.client.Timer#run() */ @Override public void run() { CmsInlineEditOverlay.updateCurrentOverlayPosition(); if (m_timerRuns > 3) { cancel(); } m_timerRuns++; } }; m_overlayTimer.scheduleRepeating(100); } /** * Sets the changed flag.

*/ void onEntityChange() { if (m_updateTimer.isScheduled()) { m_updateTimer.cancel(); } m_updateTimer.schedule(150); m_hasChanges = true; } /** * Cleanup after the edit pop-up was opened.

*/ void onPopupClose() { if (m_referenceElement != null) { CmsInlineEditOverlay.removeLastOverlay(); } CmsInlineEditOverlay.updateCurrentOverlayPosition(); if (m_entityChangeHandlerRegistration != null) { m_entityChangeHandlerRegistration.removeHandler(); } CmsAttributeHandler.setResizeHandler(null); if (!m_runningUpdate) { if (m_hasChanges) { CmsInlineEditOverlay.getRootOverlay().clearButtonPanel(); m_htmlUpdateHandler.reinitWidgets(m_formParent); } } m_popup = null; } /** Handles the remove attribute click.

* * @param event the click event */ @UiHandler("m_removeButton") void onRemoveClick(ClickEvent event) { m_attributeHandler.removeAttributeValueFromEntity(m_attributeIndex); setContentHighlightingVisible(false); runHtmlUpdate(); } /** * Positions the given pop-up relative to the reference element.

*/ void positionPopup() { if (m_popup != null) { if (m_referenceElement != null) { CmsPositionBean referencePosition = CmsPositionBean.getBoundingClientRect(m_referenceElement); int currentTop = m_popup.getAbsoluteTop(); int windowHeight = Window.getClientHeight(); int scrollTop = Window.getScrollTop(); int contentHeight = m_popup.getOffsetHeight(); int top = referencePosition.getTop(); if (((windowHeight + scrollTop) < (top + referencePosition.getHeight() + contentHeight + 20)) && ((contentHeight + 40) < top)) { top = top - contentHeight - 5; if ((currentTop < top) && ((top - currentTop) < 200)) { // keep the current position top = currentTop; } } else { top = top + referencePosition.getHeight() + 5; if ((currentTop > top) && ((currentTop - top) < 200)) { // keep the current position top = currentTop; } } m_popup.center(); m_popup.setPopupPosition(m_popup.getPopupLeft(), top); if (((contentHeight + top) - scrollTop) > windowHeight) { Window.scrollTo(Window.getScrollLeft(), ((contentHeight + top) - windowHeight) + 20); } } else { m_popup.center(); } } } /** * Updates the HTML according to the entity data.

*/ void runHtmlUpdate() { if (m_runningUpdate) { m_updateTimer.schedule(50); } else { m_runningUpdate = true; m_htmlUpdateHandler.updateHtml(m_formParent, new Command() { public void execute() { afterHtmlUpdate(); } }); } } /** * Opens the form popup.

* * @param clickEvent the click event */ @UiHandler("m_editButton") void showEditPopup(ClickEvent clickEvent) { m_editButton.clearHoverState(); m_popup = new CmsPopup(m_title, -1); m_popup.setModal(true); m_popup.setAutoHideEnabled(true); m_popup.removePadding(); m_popup.addCloseHandler(new CloseHandler() { public void onClose(CloseEvent event) { onPopupClose(); } }); m_hasChanges = false; m_requireShowPopup = false; m_entityChangeHandlerRegistration = m_parentEntity.addValueChangeHandler(new ValueChangeHandler() { public void onValueChange(ValueChangeEvent event) { onEntityChange(); } }); CmsType type = CmsEntityBackend.getInstance().getType(m_parentEntity.getTypeName()); FlowPanel formPanel = new FormPanel(); formPanel.setStyleName(I_CmsLayoutBundle.INSTANCE.form().formParent()); formPanel.getElement().getStyle().setMargin(0, Unit.PX); formPanel.getElement().getStyle().setBorderWidth(0, Unit.PX); formPanel.getElement().getStyle().setPropertyPx("minHeight", 30); m_popup.add(formPanel); m_popup.addDialogClose(null); I_CmsLayoutBundle.INSTANCE.dialogCss().ensureInjected(); m_popup.show(); CmsAttributeHandler.setScrollElement(formPanel.getElement()); CmsAttributeHandler.setResizeHandler(new ResizeHandler() { public void onResize(ResizeEvent event) { positionPopup(); } }); m_widgetService.getRendererForType(type).renderAttributeValue( m_parentEntity, m_attributeHandler, m_attributeIndex, formPanel); CmsInlineEditOverlay.addOverlayForElement(m_referenceElement); positionPopup(); m_popup.getElement().getStyle().setZIndex(I_CmsLayoutBundle.INSTANCE.constants().css().zIndexPopup()); m_popupClosed = false; } /** * Initializes the button styling.

*/ private void initButtons() { m_addButton.addChoice( m_attributeHandler.getWidgetService(), new CmsChoiceMenuEntryBean(m_attributeHandler.getAttributeName()), new AsyncCallback() { public void onFailure(Throwable caught) { // will not be called } public void onSuccess(CmsChoiceMenuEntryBean selectedEntry) { // nothing to do } }); m_addButton.addDomHandler(new ClickHandler() { public void onClick(ClickEvent event) { m_addButton.hide(); addNewAttributeValue(); event.preventDefault(); event.stopPropagation(); } }, ClickEvent.getType()); m_editButton.setImageClass(I_CmsButton.PEN_SMALL); m_editButton.setButtonStyle(ButtonStyle.FONT_ICON, null); m_removeButton.setImageClass(I_CmsButton.CUT_SMALL); m_removeButton.setButtonStyle(ButtonStyle.FONT_ICON, null); m_upButton.setImageClass(I_CmsButton.EDIT_UP_SMALL); m_upButton.setButtonStyle(ButtonStyle.FONT_ICON, null); m_downButton.setImageClass(I_CmsButton.EDIT_DOWN_SMALL); m_downButton.setButtonStyle(ButtonStyle.FONT_ICON, null); if (CmsEditorBase.hasDictionary()) { String label = m_widgetService.getAttributeLabel(m_attributeHandler.getAttributeName()); m_addButton.setTitle(CmsEditorBase.getMessageForKey(CmsEditorBase.GUI_VIEW_ADD_1, label)); m_removeButton.setTitle(CmsEditorBase.getMessageForKey(CmsEditorBase.GUI_VIEW_DELETE_1, label)); m_upButton.setTitle(CmsEditorBase.getMessageForKey(CmsEditorBase.GUI_VIEW_MOVE_UP_0)); m_downButton.setTitle(CmsEditorBase.getMessageForKey(CmsEditorBase.GUI_VIEW_MOVE_DOWN_0)); m_title = CmsEditorBase.getMessageForKey(CmsEditorBase.GUI_VIEW_EDIT_1, label); m_editButton.setTitle(m_title); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy