/*
* 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.gwt.client.property;
import org.opencms.file.CmsResource;
import org.opencms.gwt.client.Messages;
import org.opencms.gwt.client.ui.CmsNotification;
import org.opencms.gwt.client.ui.CmsNotification.Type;
import org.opencms.gwt.client.ui.input.CmsDefaultStringModel;
import org.opencms.gwt.client.ui.input.CmsSelectBox;
import org.opencms.gwt.client.ui.input.CmsTextBox;
import org.opencms.gwt.client.ui.input.I_CmsFormField;
import org.opencms.gwt.client.ui.input.I_CmsFormWidget;
import org.opencms.gwt.client.ui.input.I_CmsHasGhostValue;
import org.opencms.gwt.client.ui.input.I_CmsStringModel;
import org.opencms.gwt.client.ui.input.form.CmsBasicFormField;
import org.opencms.gwt.client.ui.input.form.CmsForm;
import org.opencms.gwt.client.ui.input.form.CmsFormDialog;
import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry;
import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetMultiFactory;
import org.opencms.gwt.shared.property.CmsClientTemplateBean;
import org.opencms.util.CmsPair;
import org.opencms.util.CmsUUID;
import org.opencms.xml.content.CmsXmlContentProperty;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
/**
* The abstract base class for dialogs to edit properties.<p>
*
* @since 8.0.0
*/
public abstract class A_CmsPropertyEditor implements I_CmsFormWidgetMultiFactory {
/** The field id for the link selector widget. */
public static final String FIELD_LINK = "field_link";
/** The field id of the "url name" form field. */
public static final String FIELD_URLNAME = "field_urlname";
/** The list of all property names. */
protected List<String> m_allProps;
/** The form dialog. */
protected CmsFormDialog m_dialog;
/** The form containing the fields. */
protected CmsForm m_form;
/** The reason to disable the form input fields. */
protected String m_disabledReason;
/** The handler for this sitemap entry editor. */
protected I_CmsPropertyEditorHandler m_handler;
/** The configuration of the properties. */
protected Map<String, CmsXmlContentProperty> m_propertyConfig;
/** The URL name field. */
protected I_CmsFormField m_urlNameField;
/** The model for the URL name field. */
protected CmsDefaultStringModel m_urlNameModel;
/**
* Creates a new sitemap entry editor.<p>
*
* @param handler the handler
* @param propertyConfig the property configuration
*/
public A_CmsPropertyEditor(
Map<String, CmsXmlContentProperty> propertyConfig,
final I_CmsPropertyEditorHandler handler) {
CmsForm form = new CmsForm(null);
m_form = form;
m_dialog = new CmsFormDialog(handler.getDialogTitle(), form);
m_handler = handler;
m_propertyConfig = removeHiddenProperties(propertyConfig);
m_dialog.setFormHandler(new CmsPropertyFormHandler(m_handler, m_dialog));
}
/**
* Checks whether a widget can be used in the sitemap entry editor, and throws an exception otherwise.<p>
*
* @param key the widget key
* @param widget the created widget
*/
public static void checkWidgetRequirements(String key, I_CmsFormWidget widget) {
if (!((widget instanceof I_CmsHasGhostValue) && (widget instanceof HasValueChangeHandlers<?>))) {
throw new CmsWidgetNotSupportedException(key);
}
}
/**
* @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetMultiFactory#createFormWidget(java.lang.String, java.util.Map)
*/
public I_CmsFormWidget createFormWidget(String key, Map<String, String> widgetParams) {
I_CmsFormWidget result = null;
if ("template".equals(key)) {
result = createTemplateSelector();
} else if (CmsTextBox.WIDGET_TYPE.equals(key)) {
CmsTextBox textBox = new CmsTextBox();
textBox.setErrorMessageWidth("345px");
// we need this because the tab containing the text box may not be visible
// at the time the error message is set, so measuring the field's size would
// yield an invalid value
result = textBox;
} else {
result = CmsWidgetFactoryRegistry.instance().createFormWidget(key, widgetParams);
checkWidgetRequirements(key, result);
}
return result;
}
/**
* Disables all input to the form.<p>
*
* @param disabledReason the reason to display to the user
*/
public void disableInput(String disabledReason) {
m_disabledReason = disabledReason;
for (I_CmsFormField field : m_form.getFields().values()) {
field.getWidget().setEnabled(false);
}
m_urlNameField.getWidget().setEnabled(false);
m_dialog.getOkButton().disable(m_disabledReason);
CmsNotification.get().send(Type.WARNING, m_disabledReason);
}
/**
* Sets the names of properties which can be edited.<p>
*
* @param propertyNames the property names
*/
public void setPropertyNames(List<String> propertyNames) {
m_allProps = propertyNames;
}
/**
* Shows the sitemap entry editor to the user.<p>
*/
public void start() {
CmsForm form = m_dialog.getForm();
// creates tabs, etc. if necessary
setupFieldContainer();
String firstTab = form.getWidget().getDefaultGroup();
if (m_handler.hasEditableName()) {
// the root entry name can't be edited
CmsBasicFormField urlNameField = createUrlNameField();
form.addField(firstTab, urlNameField);
}
// create fields and add them to the correct location
buildFields();
form.setValidatorClass("org.opencms.gwt.CmsDefaultFormValidator");
form.render();
m_dialog.centerHorizontally(50);
m_dialog.catchNotifications();
}
/**
* Builds and renders the fields for the properties.<p>
*/
protected abstract void buildFields();
/**
* Creates the text field for editing the URL name.<p>
*
* @return the newly created form field
*/
protected CmsBasicFormField createUrlNameField() {
if (m_urlNameField != null) {
m_urlNameField.unbind();
}
String description = message(Messages.GUI_URLNAME_PROPERTY_DESC_0);
String label = message(Messages.GUI_URLNAME_PROPERTY_0);
final CmsTextBox textbox = new CmsTextBox();
CmsBasicFormField result = new CmsBasicFormField(FIELD_URLNAME, description, label, null, textbox);
String urlName = m_handler.getName();
if (urlName == null) {
urlName = "";
}
String parent = CmsResource.getParentFolder(m_handler.getPath());
CmsUUID id = m_handler.getId();
result.setValidator(new CmsUrlNameValidator(parent, id));
I_CmsStringModel model = getUrlNameModel(urlName);
result.getWidget().setFormValueAsString(model.getValue());
result.bind(model);
//result.getWidget().setFormValueAsString(getUrlNameModel().getValue());
m_urlNameField = result;
return result;
}
/**
* Gets the title from a map of field values.<p>
*
* @param fieldValues the map of field values
* @return the title
*/
protected String getTitle(Map<String, String> fieldValues) {
for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
if (entry.getKey().contains("/NavText/")) {
return entry.getValue();
}
}
return null;
}
/**
* Lazily creates the model object for the URL name field.<p>
*
* @param urlName the initial value for the URL name
*
* @return the model object for the URL name field
*/
protected CmsDefaultStringModel getUrlNameModel(String urlName) {
if (m_urlNameModel == null) {
m_urlNameModel = new CmsDefaultStringModel("urlname");
m_urlNameModel.setValue(urlName, false);
}
return m_urlNameModel;
}
/**
* Returns a localized message from the message bundle.<p>
*
* @param key the message key
* @param args the message parameters
*
* @return the localized message
*/
protected String message(String key, Object... args) {
return Messages.get().key(key, args);
}
/**
* Sets the ghost value for a form field if its normal value is empty and the field's widget supports ghost values.<p>
*
* @param field the form field
* @param value the ghost value to set
* @param ghostMode if true, sets the widget to ghost mode
*/
protected void setGhostValue(I_CmsFormField field, String value, boolean ghostMode) {
I_CmsFormWidget widget = field.getWidget();
if ((widget instanceof I_CmsHasGhostValue) && (value != null)) {
((I_CmsHasGhostValue)widget).setGhostValue(value, ghostMode);
}
}
/**
* Sets up the widget which will contain the input fields for the properties.<p>
*/
protected abstract void setupFieldContainer();
/**
* Sets the contents of the URL name field in the form.<p>
*
* @param urlName the new URL name
*/
protected void setUrlNameField(String urlName) {
m_dialog.getForm().getField(FIELD_URLNAME).getWidget().setFormValueAsString(urlName);
}
/**
* Shows an error message next to the URL name input field.<p>
*
* @param message the message which should be displayed, or null if no message should be displayed
*/
protected void showUrlNameError(String message) {
m_dialog.getForm().getField(FIELD_URLNAME).getWidget().setErrorMessage(message);
}
/**
* Helper method for creating the template selection widget.<p>
*
* @return the template selector widget
*/
private I_CmsFormWidget createTemplateSelector() {
if (m_handler.useAdeTemplates()) {
CmsSelectBox selectBox = new CmsSelectBox(new ArrayList<CmsPair<String, String>>());
Map<String, String> values = new LinkedHashMap<String, String>();
for (Map.Entry<String, CmsClientTemplateBean> templateEntry : m_handler.getPossibleTemplates().entrySet()) {
CmsClientTemplateBean template = templateEntry.getValue();
String title = template.getTitle();
if ((title == null) || (title.length() == 0)) {
title = template.getSitePath();
}
values.put(template.getSitePath(), title);
}
selectBox = new CmsSelectBox(values, true);
return selectBox;
} else {
CmsTextBox textbox = new CmsTextBox();
return textbox;
}
}
/**
* Helper method for removing hidden properties from a map of property configurations.<p>
*
* The map passed into the method is not changed; a map which only contains the non-hidden
* property definitions is returned.<p>
*
* @param propConfig the property configuration
*
* @return the filtered property configuration
*/
private Map<String, CmsXmlContentProperty> removeHiddenProperties(Map<String, CmsXmlContentProperty> propConfig) {
Map<String, CmsXmlContentProperty> result = new LinkedHashMap<String, CmsXmlContentProperty>();
for (Map.Entry<String, CmsXmlContentProperty> entry : propConfig.entrySet()) {
if (!m_handler.isHiddenProperty(entry.getKey())) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}
}