/*
* 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.containerpage.client.ui;
import org.opencms.ade.containerpage.client.CmsContainerpageController;
import org.opencms.ade.containerpage.client.CmsContainerpageHandler;
import org.opencms.ade.containerpage.client.Messages;
import org.opencms.ade.containerpage.client.ui.css.I_CmsLayoutBundle;
import org.opencms.ade.containerpage.shared.CmsContainerElement;
import org.opencms.ade.containerpage.shared.CmsContainerElementData;
import org.opencms.ade.containerpage.shared.CmsGroupContainer;
import org.opencms.gwt.client.ui.CmsPopup;
import org.opencms.gwt.client.ui.CmsPushButton;
import org.opencms.gwt.client.ui.I_CmsButton.ButtonColor;
import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
import org.opencms.gwt.client.ui.css.I_CmsToolbarButtonLayoutBundle;
import org.opencms.gwt.client.ui.input.CmsLabel;
import org.opencms.gwt.client.ui.input.CmsTextBox;
import org.opencms.gwt.client.util.CmsDebugLog;
import org.opencms.gwt.client.util.CmsDomUtil;
import org.opencms.gwt.client.util.CmsPositionBean;
import org.opencms.gwt.client.util.I_CmsSimpleCallback;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
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.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* The group-container editor.<p>
*
* @since 8.0.0
*/
public final class CmsGroupcontainerEditor extends Composite {
/** The ui-binder interface for this widget. */
interface I_CmsGroupcontainerEditorUiBinder extends UiBinder<HTMLPanel, CmsGroupcontainerEditor> {
// GWT interface, nothing to do here
}
/** The current group container instance. */
private static CmsGroupcontainerEditor INSTANCE;
/** The ui-binder for this widget. */
private static I_CmsGroupcontainerEditorUiBinder uiBinder = GWT.create(I_CmsGroupcontainerEditorUiBinder.class);
/** The container marker div element. */
@UiField
protected DivElement m_containerMarker;
/** The dialog element. */
@UiField
protected HTMLPanel m_dialogContent;
/** The description input. */
@UiField
protected CmsTextBox m_inputDescription;
/** The title input. */
@UiField
protected CmsTextBox m_inputTitle;
/** The descriptionLabel. */
@UiField
protected CmsLabel m_labelDescription;
/** The title label. */
@UiField
protected CmsLabel m_labelTitle;
/** The overlay div element. */
@UiField
protected DivElement m_overlayDiv;
/** List of elements when editing started, use to restore on cancel. */
private List<CmsContainerPageElementPanel> m_backUpElements;
/** The dialog break up group container button. */
private CmsPushButton m_breakUpButton;
/** The dialog cancel button. */
private CmsPushButton m_cancelButton;
/** The container-page controller. */
private CmsContainerpageController m_controller;
/** The group-container place-holder. */
private Element m_editingPlaceholder;
/** The editor popup dialog. */
private CmsPopup m_editorDialog;
/** The editor HTML-id. */
private String m_editorId;
/** The editor widget. */
private HTMLPanel m_editorWidget;
/** The container element data. */
private CmsContainerElementData m_elementData;
/** The group-container. */
private CmsGroupContainerElementPanel m_groupContainer;
/** The group container bean. */
private CmsGroupContainer m_groupContainerBean;
/** The group container element position. */
private CmsPositionBean m_groupContainerPosition;
/** The index position of the group-container inside it's parent. */
private int m_indexPosition;
/** The parent container. */
private CmsContainerPageContainer m_parentContainer;
/** The dialog save button. */
private CmsPushButton m_saveButton;
/**
* Constructor.<p>
*
* @param groupContainer the group-container
* @param controller the container-page controller
* @param handler the container-page handler
*/
private CmsGroupcontainerEditor(
CmsGroupContainerElementPanel groupContainer,
CmsContainerpageController controller,
CmsContainerpageHandler handler) {
m_controller = controller;
m_editorWidget = uiBinder.createAndBindUi(this);
initWidget(m_editorWidget);
m_overlayDiv.getStyle().setZIndex(I_CmsLayoutBundle.INSTANCE.constants().css().zIndexHighlighting());
m_labelDescription.setText(Messages.get().key(Messages.GUI_GROUPCONTAINER_LABEL_DESCRIPTION_0));
m_labelTitle.setText(Messages.get().key(Messages.GUI_GROUPCONTAINER_LABEL_TITLE_0));
m_editorId = HTMLPanel.createUniqueId();
m_editorWidget.getElement().setId(m_editorId);
m_groupContainer = groupContainer;
m_backUpElements = new ArrayList<CmsContainerPageElementPanel>();
Iterator<Widget> it = m_groupContainer.iterator();
while (it.hasNext()) {
Widget w = it.next();
if (w instanceof CmsContainerPageElementPanel) {
m_backUpElements.add((CmsContainerPageElementPanel)w);
}
}
m_parentContainer = (CmsContainerPageContainer)m_groupContainer.getParentTarget();
m_groupContainerPosition = CmsPositionBean.generatePositionInfo(m_groupContainer);
m_editingPlaceholder = createPlaceholder(m_groupContainer.getElement());
m_groupContainer.setEditingPlaceholder(m_editingPlaceholder);
m_groupContainer.setEditingMarker(m_containerMarker);
m_indexPosition = m_parentContainer.getWidgetIndex(m_groupContainer);
// inserting placeholder element
m_parentContainer.getElement().insertBefore(m_editingPlaceholder, m_groupContainer.getElement());
m_editorWidget.add(m_groupContainer, m_editorId);
Style style = m_groupContainer.getElement().getStyle();
style.setPosition(Position.ABSOLUTE);
style.setLeft(m_groupContainerPosition.getLeft(), Unit.PX);
style.setTop(m_groupContainerPosition.getTop(), Unit.PX);
style.setWidth(m_groupContainerPosition.getWidth(), Unit.PX);
style.setZIndex(I_CmsLayoutBundle.INSTANCE.constants().css().zIndexGroupContainer());
m_containerMarker.getStyle().setLeft(m_groupContainerPosition.getLeft() - 3, Unit.PX);
m_containerMarker.getStyle().setTop(m_groupContainerPosition.getTop() - 4, Unit.PX);
m_containerMarker.getStyle().setWidth(m_groupContainerPosition.getWidth() + 4, Unit.PX);
m_containerMarker.getStyle().setHeight(m_groupContainerPosition.getHeight() + 4, Unit.PX);
m_groupContainer.getElementOptionBar().setVisible(false);
m_groupContainer.getElementOptionBar().removeStyleName(
I_CmsToolbarButtonLayoutBundle.INSTANCE.toolbarButtonCss().cmsHovering());
RootPanel.get().addStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().groupcontainerEditing());
// Loading data of all contained elements including group-container element
m_controller.getElements(getElementIds(), new I_CmsSimpleCallback<Map<String, CmsContainerElementData>>() {
public void execute(Map<String, CmsContainerElementData> arg) {
setGroupContainerData(arg);
}
});
}
/**
* Opens the group-container editor.<p>
*
* @param groupContainer the group-container
* @param controller the container-page controller
* @param handler the container-page handler
*/
public static void openGroupcontainerEditor(
CmsGroupContainerElementPanel groupContainer,
CmsContainerpageController controller,
CmsContainerpageHandler handler) {
// making sure only a single instance of the group-container editor is open
if (INSTANCE != null) {
CmsDebugLog.getInstance().printLine("group-container editor already open");
} else {
if (controller.startEditingGroupcontainer(groupContainer)) {
INSTANCE = new CmsGroupcontainerEditor(groupContainer, controller, handler);
RootPanel.get().add(INSTANCE);
INSTANCE.openDialog();
}
}
}
/**
* Breaks up the group container inserting it's elements into the parent container instead.<p>
*/
protected void breakUpContainer() {
final List<CmsContainerElement> elements = getElements();
if (elements.isEmpty()) {
m_controller.setPageChanged();
closeDialog(true);
return;
}
Set<String> elementIds = new HashSet<String>();
for (CmsContainerElement element : elements) {
elementIds.add(element.getClientId());
}
I_CmsSimpleCallback<Map<String, CmsContainerElementData>> callback = new I_CmsSimpleCallback<Map<String, CmsContainerElementData>>() {
public void execute(Map<String, CmsContainerElementData> elementsData) {
breakUpContainer(elements, elementsData);
}
};
m_controller.getElements(elementIds, callback);
}
/**
* Breaks up the group container inserting the given elements into the parent container instead.<p>
*
* @param elements the group container elements
* @param elementsData the elements data
*/
protected void breakUpContainer(
List<CmsContainerElement> elements,
Map<String, CmsContainerElementData> elementsData) {
int index = m_indexPosition;
for (CmsContainerElement element : elements) {
try {
CmsContainerPageElementPanel containerElement = m_controller.getContainerpageUtil().createElement(
elementsData.get(element.getClientId()),
m_parentContainer);
m_parentContainer.insert(containerElement, index);
index++;
} catch (Exception e) {
CmsDebugLog.getInstance().printLine(e.getMessage());
}
}
m_controller.addToRecentList(m_groupContainerBean.getClientId());
m_controller.setPageChanged();
closeDialog(true);
}
/**
* On click function for cancel button.<p>
*/
protected void cancelEdit() {
Iterator<Widget> it = m_groupContainer.iterator();
while (it.hasNext()) {
Widget w = it.next();
if (w instanceof CmsContainerPageElementPanel) {
w.removeFromParent();
}
}
for (CmsContainerPageElementPanel element : m_backUpElements) {
m_groupContainer.add(element);
}
if (m_backUpElements.size() == 0) {
m_groupContainer.addStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().emptyGroupContainer());
}
closeDialog(false);
}
/**
* Closes the dialog.<p>
*
* @param breakingUp <code>true</code> if the group container is to be removed
*/
protected void closeDialog(boolean breakingUp) {
m_controller.stopEditingGroupcontainer();
m_editingPlaceholder.removeFromParent();
m_editorDialog.hide();
RootPanel.get().removeStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().groupcontainerEditing());
if (!breakingUp) {
m_groupContainer.clearEditingPlaceholder();
Style style = m_groupContainer.getElement().getStyle();
style.clearPosition();
style.clearTop();
style.clearLeft();
style.clearZIndex();
style.clearWidth();
m_parentContainer.insert(m_groupContainer, m_indexPosition);
m_groupContainer.getElementOptionBar().setVisible(true);
if (!m_groupContainer.iterator().hasNext()) {
// group-container is empty, mark it
m_groupContainer.addStyleName(I_CmsLayoutBundle.INSTANCE.containerpageCss().emptyGroupContainer());
}
}
INSTANCE = null;
this.removeFromParent();
}
/**
* Creates a place-holder for the group-container.<p>
*
* @param element the element
*
* @return the place-holder widget
*/
protected Element createPlaceholder(Element element) {
Element result = CmsDomUtil.clone(element);
result.addClassName(I_CmsLayoutBundle.INSTANCE.containerpageCss().groupcontainerPlaceholder());
result.getStyle().setBackgroundColor("transparent");
return result;
}
/**
* On click function for save button.<p>
*/
protected void saveEdit() {
m_groupContainerBean.setTitle(m_inputTitle.getFormValueAsString());
m_groupContainerBean.setDescription(m_inputDescription.getFormValueAsString());
m_groupContainerBean.setElements(getElements());
m_controller.saveGroupcontainer(m_groupContainerBean, m_groupContainer);
closeDialog(false);
}
/**
* Sets the data of the group-container to edit.<p>
*
* @param elementsData the data of all contained elements and the group-container itself
*/
protected void setGroupContainerData(Map<String, CmsContainerElementData> elementsData) {
m_elementData = elementsData.get(m_groupContainer.getId());
if (m_elementData != null) {
if (m_saveButton != null) {
m_saveButton.enable();
}
m_groupContainerBean = new CmsGroupContainer();
m_groupContainerBean.setClientId(m_elementData.getClientId());
m_groupContainerBean.setResourceType(m_groupContainer.getNewType());
m_groupContainerBean.setNew(m_groupContainer.isNew());
m_groupContainerBean.setSitePath(m_elementData.getSitePath());
if (m_elementData.getTypes().isEmpty()) {
Set<String> types = new HashSet<String>();
types.add(((CmsContainerPageContainer)m_groupContainer.getParentTarget()).getContainerType());
m_elementData.setTypes(types);
m_groupContainerBean.setTypes(types);
} else {
m_groupContainerBean.setTypes(m_elementData.getTypes());
}
m_inputDescription.setFormValueAsString(m_elementData.getDescription());
m_inputTitle.setFormValueAsString(m_elementData.getTitle());
m_groupContainerBean.setTitle(m_elementData.getTitle());
m_groupContainerBean.setDescription(m_elementData.getDescription());
} else {
CmsDebugLog.getInstance().printLine("Loading groupcontainer error.");
}
}
/**
* Returns the ids of the contained elements and group-container itself.<p>
*
* @return the element ids
*/
private Set<String> getElementIds() {
Set<String> subItems = new HashSet<String>();
Iterator<Widget> it = m_groupContainer.iterator();
while (it.hasNext()) {
Widget w = it.next();
if (w instanceof CmsContainerPageElementPanel) {
subItems.add(((CmsContainerPageElementPanel)w).getId());
}
}
subItems.add(m_groupContainer.getId());
return subItems;
}
/**
* Returns the element data of the contained elements.<p>
*
* @return the contained elements data
*/
private List<CmsContainerElement> getElements() {
List<CmsContainerElement> subItems = new ArrayList<CmsContainerElement>();
Iterator<Widget> it = m_groupContainer.iterator();
while (it.hasNext()) {
Widget w = it.next();
if (w instanceof CmsContainerPageElementPanel) {
CmsContainerPageElementPanel elementWidget = (CmsContainerPageElementPanel)w;
CmsContainerElement element = new CmsContainerElement();
element.setClientId(elementWidget.getId());
element.setResourceType(elementWidget.getNewType());
element.setNew(elementWidget.isNew());
element.setSitePath(elementWidget.getSitePath());
subItems.add(element);
}
}
return subItems;
}
/**
* Opens the group container edit dialog.<p>
*/
private void openDialog() {
m_editorDialog = new CmsPopup(Messages.get().key(Messages.GUI_GROUPCONTAINER_CAPTION_0), 500);
int contentHeight = m_dialogContent.getOffsetHeight();
m_editorDialog.setMainContent(m_dialogContent);
m_cancelButton = new CmsPushButton();
m_cancelButton.setText(Messages.get().key(Messages.GUI_BUTTON_CANCEL_TEXT_0));
m_cancelButton.setUseMinWidth(true);
m_cancelButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.BLUE);
m_cancelButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
cancelEdit();
}
});
m_editorDialog.addButton(m_cancelButton);
m_breakUpButton = new CmsPushButton();
m_breakUpButton.setText(Messages.get().key(Messages.GUI_BUTTON_BREAK_UP_TEXT_0));
m_breakUpButton.setUseMinWidth(true);
m_breakUpButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.RED);
m_breakUpButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
breakUpContainer();
}
});
m_editorDialog.addButton(m_breakUpButton);
m_saveButton = new CmsPushButton();
m_saveButton.setText(Messages.get().key(Messages.GUI_BUTTON_SAVE_TEXT_0));
m_saveButton.setUseMinWidth(true);
m_saveButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.GREEN);
m_saveButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
saveEdit();
}
});
m_editorDialog.addButton(m_saveButton);
if (m_elementData == null) {
m_saveButton.disable(Messages.get().key(Messages.GUI_GROUPCONTAINER_LOADING_DATA_0));
}
m_editorDialog.setGlassEnabled(false);
m_editorDialog.setModal(false);
m_editorDialog.addDialogClose(new Command() {
/**
* @see com.google.gwt.user.client.Command#execute()
*/
public void execute() {
cancelEdit();
}
});
if (m_groupContainerPosition != null) {
if (m_groupContainerPosition.getLeft() > 600) {
// place left of the group container if there is enough space
m_editorDialog.setPopupPosition(
m_groupContainerPosition.getLeft() - 530,
m_groupContainerPosition.getTop() - 1);
} else if (m_groupContainerPosition.getTop() > (contentHeight + 103 + 40)) {
// else place above if there is enough space
m_editorDialog.setPopupPosition(m_groupContainerPosition.getLeft(), m_groupContainerPosition.getTop()
- (contentHeight + 103));
} else {
// else on the right
m_editorDialog.setPopupPosition(
m_groupContainerPosition.getLeft() + m_groupContainerPosition.getWidth() + 20,
m_groupContainerPosition.getTop() - 1);
}
m_editorDialog.show();
} else {
// should never happen
m_editorDialog.center();
}
}
}