001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ade.containerpage.client.ui;
029
030import org.opencms.ade.containerpage.client.CmsContainerpageController;
031import org.opencms.ade.containerpage.client.Messages;
032import org.opencms.ade.containerpage.client.ui.groupeditor.CmsInheritanceContainerEditor;
033import org.opencms.ade.containerpage.shared.CmsContainerElement;
034import org.opencms.ade.containerpage.shared.CmsContainerElement.ModelGroupState;
035import org.opencms.ade.containerpage.shared.CmsContainerElementData;
036import org.opencms.ade.containerpage.shared.CmsElementSettingsConfig;
037import org.opencms.ade.containerpage.shared.CmsFormatterConfig;
038import org.opencms.ade.containerpage.shared.CmsFormatterConfigCollection;
039import org.opencms.gwt.client.CmsCoreProvider;
040import org.opencms.gwt.client.ui.CmsFieldSet;
041import org.opencms.gwt.client.ui.contextmenu.CmsContextMenuButton;
042import org.opencms.gwt.client.ui.contextmenu.CmsDialogContextMenuHandler;
043import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle;
044import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
045import org.opencms.gwt.client.ui.input.CmsCheckBox;
046import org.opencms.gwt.client.ui.input.CmsMultiCheckBox;
047import org.opencms.gwt.client.ui.input.CmsSelectBox;
048import org.opencms.gwt.client.ui.input.CmsSelectComboBox;
049import org.opencms.gwt.client.ui.input.I_CmsFormField;
050import org.opencms.gwt.client.ui.input.I_CmsFormWidget;
051import org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel;
052import org.opencms.gwt.client.ui.input.form.CmsBasicFormField;
053import org.opencms.gwt.client.ui.input.form.CmsDialogFormHandler;
054import org.opencms.gwt.client.ui.input.form.CmsFieldTooltip;
055import org.opencms.gwt.client.ui.input.form.CmsFieldTooltip.Data;
056import org.opencms.gwt.client.ui.input.form.CmsFieldsetFormFieldPanel;
057import org.opencms.gwt.client.ui.input.form.CmsForm;
058import org.opencms.gwt.client.ui.input.form.CmsFormDialog;
059import org.opencms.gwt.client.ui.input.form.CmsFormRow;
060import org.opencms.gwt.client.ui.input.form.CmsInfoBoxFormFieldPanel;
061import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry;
062import org.opencms.gwt.client.ui.input.form.I_CmsFormSubmitHandler;
063import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetMultiFactory;
064import org.opencms.gwt.client.util.CmsDomUtil;
065import org.opencms.gwt.client.util.I_CmsSimpleCallback;
066import org.opencms.gwt.shared.CmsAdditionalInfoBean;
067import org.opencms.gwt.shared.CmsCoreData.AdeContext;
068import org.opencms.gwt.shared.CmsGwtConstants;
069import org.opencms.gwt.shared.CmsListInfoBean;
070import org.opencms.gwt.shared.CmsTemplateContextInfo;
071import org.opencms.util.CmsStringUtil;
072import org.opencms.util.CmsUUID;
073import org.opencms.xml.content.CmsXmlContentProperty;
074
075import java.util.ArrayList;
076import java.util.Collections;
077import java.util.HashMap;
078import java.util.LinkedHashMap;
079import java.util.List;
080import java.util.Map;
081import java.util.Map.Entry;
082import java.util.Set;
083
084import com.google.common.base.Optional;
085import com.google.common.base.Supplier;
086import com.google.common.collect.Maps;
087import com.google.gwt.dom.client.Style;
088import com.google.gwt.dom.client.Style.Unit;
089import com.google.gwt.event.logical.shared.ValueChangeEvent;
090import com.google.gwt.event.logical.shared.ValueChangeHandler;
091import com.google.gwt.user.client.ui.FlowPanel;
092import com.google.gwt.user.client.ui.Widget;
093
094/**
095 * The element settings dialog.<p>
096 */
097public class CmsElementSettingsDialog extends CmsFormDialog implements I_CmsFormWidgetMultiFactory {
098
099    /**
100     * A panel which adds icons with tooltips containing the field description to the rows.<p>
101     */
102    public static class FieldPanel extends CmsFieldsetFormFieldPanel {
103
104        /**
105         * Creates a new instance.<p>
106         *
107         * @param info the list info bean for an element
108         * @param legend the legend for the fieldset
109         */
110        public FieldPanel(CmsListInfoBean info, String legend) {
111
112            super(info, legend);
113        }
114
115        /**
116         * @see org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel#createRow(org.opencms.gwt.client.ui.input.I_CmsFormField)
117         */
118        @Override
119        protected CmsFormRow createRow(I_CmsFormField field) {
120
121            final String htmlDesc = field.getDescription();
122            CmsFormRow row = createRow(
123                field.getLabel(),
124                A_CmsFormFieldPanel.NO_DESCRIPTION,
125                (Widget)field.getWidget(),
126                htmlDesc,
127                true);
128            return row;
129        }
130
131    }
132
133    /**
134     * Exception for the case where no formatter configuration is available.<p>
135     */
136    public static class NoFormatterException extends Exception {
137
138        /** uid. */
139        private static final long serialVersionUID = -5735428472483535958L;
140
141        /**
142         * Creates a new instance.<p>
143         */
144        public NoFormatterException() {
145
146            // nothing here
147        }
148    }
149
150    /** The model group options. */
151    protected enum GroupOption {
152
153        /** The copy elements option. */
154        copy(Messages.get().key(Messages.GUI_MODEL_GROUP_OPTION_COPY_0)),
155
156        /** The disabled option. */
157        disabled(Messages.get().key(Messages.GUI_MODEL_GROUP_OPTION_DISABLED_0)),
158
159        /** The reuse option. */
160        reuse(Messages.get().key(Messages.GUI_MODEL_GROUP_OPTION_REUSE_0));
161
162        /** The option label. */
163        private String m_label;
164
165        /**
166         * Constructor.<p>
167         *
168         * @param label the label
169         */
170        GroupOption(String label) {
171
172            m_label = label;
173        }
174
175        /**
176         * Returns the option label.<p>
177         *
178         * @return the option label
179         */
180        protected String getLabel() {
181
182            return m_label;
183        }
184    }
185
186    /** The hidden field widget name. */
187    private static final String HIDDEN_FIELD_WIDGET = "hidden";
188
189    /** The container page controller. */
190    CmsContainerpageController m_controller;
191
192    /** Checkbox to set the 'model group' status. */
193    CmsSelectBox m_modelGroupSelect;
194
195    /** The template context changed flag. */
196    private boolean m_changedContext;
197
198    /** The current container id. */
199    private String m_containerId;
200
201    /** The template context info. */
202    private CmsTemplateContextInfo m_contextInfo;
203
204    /** The template context widget. */
205    private CmsMultiCheckBox m_contextsWidget;
206
207    /** Checkbox to set the 'createNew' status. */
208    private CmsCheckBox m_createNewCheckBox;
209
210    /** The element data bean. */
211    private CmsContainerElementData m_elementBean;
212
213    /** The element panel. */
214    private CmsContainerPageElementPanel m_elementWidget;
215
216    /** Id of currently selected formatter. */
217    private String m_formatter;
218
219    /** The formatter select widget. */
220    private CmsSelectBox m_formatterSelect;
221
222    /** The break up model group checkbox. */
223    private CmsCheckBox m_modelGroupBreakUp;
224
225    /** Setting presets. */
226    private Map<String, String> m_presets;
227
228    /** The element setting values. */
229    private Map<String, String> m_settings;
230
231    /**
232     * Constructor.<p>
233     *
234     * @param controller the container page controller
235     * @param elementWidget the element panel
236     * @param settingsConfig the element setting configuration
237     * @param settingPresets the presets for settings
238     *
239     * @throws NoFormatterException if no formatter configuration is found for the element
240     */
241    public CmsElementSettingsDialog(
242        CmsContainerpageController controller,
243        CmsContainerPageElementPanel elementWidget,
244        CmsElementSettingsConfig settingsConfig,
245        Map<String, String> settingPresets)
246    throws NoFormatterException {
247
248        super(Messages.get().key(Messages.GUI_PROPERTY_DIALOG_TITLE_0), new CmsForm(false), null);
249        setAnimationEnabled(false);
250        setUseAnimation(false);
251        addStyleName(I_CmsLayoutBundle.INSTANCE.elementSettingsDialogCss().elementSettingsDialog());
252        m_presets = settingPresets != null ? settingPresets : new HashMap<String, String>();
253        CmsContainerElementData elementBean = settingsConfig.getElementData();
254        m_elementWidget = elementWidget;
255        m_controller = controller;
256        m_elementBean = elementBean;
257        m_contextInfo = m_controller.getData().getTemplateContextInfo();
258        m_containerId = m_elementWidget.getParentTarget().getContainerId();
259        CmsListInfoBean infoBean = new CmsListInfoBean();
260        infoBean.setResourceState(settingsConfig.getState());
261        infoBean.setTitle(elementBean.getTitle());
262        infoBean.setSubTitle(elementBean.getSitePath());
263        infoBean.setResourceType(elementBean.getResourceType());
264        infoBean.setBigIconClasses(elementBean.getBigIconClasses());
265        m_settings = elementBean.getSettings();
266        A_CmsFormFieldPanel formFieldPanel = null;
267        CmsFormatterConfig currentFormatterConfig = m_elementBean.getFormatterConfig(m_containerId);
268        if (currentFormatterConfig == null) {
269            throw new NoFormatterException();
270        }
271        for (CmsAdditionalInfoBean addInfo : settingsConfig.getAdditionalInfo()) {
272            infoBean.addAdditionalInfo(addInfo.getName(), addInfo.getValue(), addInfo.getStyle());
273        }
274        // infoBean.addAdditionalInfo(Messages.get().key(Messages.GUI_ADDINFO_FORMATTER_PATH_0), formatterPath);
275        I_CmsDropContainer dropContainer = elementWidget.getParentTarget();
276        if (dropContainer instanceof CmsContainerPageContainer) {
277            CmsContainerPageContainer cpc = (CmsContainerPageContainer)dropContainer;
278            String type = cpc.getContainerType();
279            String name = cpc.getContainerId();
280            infoBean.addAdditionalInfo(Messages.get().key(Messages.GUI_ADDINFO_FORMATTER_CONTAINER_0), name);
281            infoBean.addAdditionalInfo(Messages.get().key(Messages.GUI_ADDINFO_FORMATTER_CONTAINER_TYPE_0), type);
282        }
283
284        boolean isEditableModelGroup = CmsCoreProvider.get().getUserInfo().isDeveloper()
285            && m_controller.getData().isModelGroup()
286            && ((m_controller.getModelGroupElementId() == null)
287                || CmsContainerpageController.getServerId(elementBean.getClientId()).equals(
288                    m_controller.getModelGroupElementId()));
289        boolean isDeveloper = CmsCoreProvider.get().getUserInfo().isDeveloper();
290        if (m_contextInfo.shouldShowElementTemplateContextSelection()
291            || isDeveloper
292            || m_elementBean.hasAlternativeFormatters(m_containerId)) {
293            CmsFieldsetFormFieldPanel fieldSetPanel = new FieldPanel(
294                infoBean,
295                Messages.get().key(Messages.GUI_SETTINGS_LEGEND_0));
296            formFieldPanel = fieldSetPanel;
297            if (m_elementBean.hasAlternativeFormatters(m_containerId)) {
298                CmsFieldSet formatterFieldset = new CmsFieldSet();
299                // insert as first field-set after the element info box
300                fieldSetPanel.getMainPanel().insert(formatterFieldset, 1);
301                formatterFieldset.setLegend(Messages.get().key(Messages.GUI_FORMATTERS_LEGEND_0));
302                formatterFieldset.getElement().getStyle().setMarginTop(10, Style.Unit.PX);
303                LinkedHashMap<String, String> formatters = new LinkedHashMap<String, String>();
304                CmsElementSettingsFormatterWidget formatterWidget = new CmsElementSettingsFormatterWidget();
305                m_formatterSelect = formatterWidget.getFormatterSelect();
306                CmsFormatterConfigCollection formattersForContainer = m_elementBean.getFormatters().get(m_containerId);
307                for (CmsFormatterConfig formatter : formattersForContainer) {
308                    formatters.put(formatter.getKeyOrId(), formatter.getLabel());
309                    m_formatterSelect.setTitle(formatter.getKeyOrId(), formatter.getJspRootPath());
310                }
311                m_formatterSelect.setItems(formatters);
312                String currentFormatterValue = m_elementBean.getFormatterConfig(m_containerId).getKeyOrId();
313                m_formatter = currentFormatterValue;
314                m_formatterSelect.selectValue(currentFormatterValue);
315                m_formatterSelect.addValueChangeHandler(new ValueChangeHandler<String>() {
316
317                    public void onValueChange(ValueChangeEvent<String> event) {
318
319                        onFormatterChange(event.getValue());
320                    }
321                });
322
323                // set up formatter help tooltip
324                final FlowPanel help = formatterWidget.getHelp();
325                for (String style : CmsFormRow.ICON_STYLES) {
326                    help.addStyleName(style);
327                }
328                final Map<String, CmsFieldTooltip.Data> tooltips = Maps.newHashMap();
329                for (CmsFormatterConfig formatterConfig : formattersForContainer) {
330                    String description = formatterConfig.getDescription();
331                    if (description == null) {
332                        description = formatterConfig.getLabel();
333                    }
334                    tooltips.put(formatterConfig.getId(), new Data(help, description, true));
335                }
336                Supplier<CmsFieldTooltip.Data> tooltipProvider = new Supplier<CmsFieldTooltip.Data>() {
337
338                    @SuppressWarnings("synthetic-access")
339                    public Data get() {
340
341                        return tooltips.get(m_formatter);
342                    }
343                };
344                CmsFormRow.installTooltipEventHandlers(help, tooltipProvider);
345                formatterFieldset.add(formatterWidget);
346            }
347            if (m_controller.getData().isModelPage() || isEditableModelGroup) {
348                CmsFieldSet modelGroupFieldSet = new CmsFieldSet();
349                modelGroupFieldSet.setLegend(Messages.get().key(Messages.GUI_CREATE_NEW_LEGEND_0
350
351                ));
352                modelGroupFieldSet.getElement().getStyle().setMarginTop(10, Unit.PX);
353
354                if (isEditableModelGroup && !elementWidget.hasModelGroupParent()) {
355                    addModelGroupSettings(elementBean, elementWidget, modelGroupFieldSet);
356                } else if (!elementWidget.isModelGroup()) {
357                    addCreateNewCheckbox(elementBean, modelGroupFieldSet);
358                }
359                if (modelGroupFieldSet.getWidgetCount() > 0) {
360                    fieldSetPanel.getMainPanel().insert(modelGroupFieldSet, 1);
361                }
362
363            } else if (elementWidget.isModelGroup()) {
364                CmsFieldSet modelGroupFieldSet = new CmsFieldSet();
365                modelGroupFieldSet.setLegend(Messages.get().key(Messages.GUI_CREATE_NEW_LEGEND_0
366
367                ));
368                modelGroupFieldSet.getElement().getStyle().setMarginTop(10, Unit.PX);
369                m_modelGroupBreakUp = new CmsCheckBox(Messages.get().key(Messages.GUI_MODEL_GROUP_BREAK_UP_0));
370                m_modelGroupBreakUp.setDisplayInline(false);
371                m_modelGroupBreakUp.getElement().getStyle().setMarginTop(7, Style.Unit.PX);
372                modelGroupFieldSet.add(m_modelGroupBreakUp);
373                fieldSetPanel.getMainPanel().insert(modelGroupFieldSet, 1);
374            }
375
376            if (m_contextInfo.shouldShowElementTemplateContextSelection()) {
377                String templateContexts = m_settings.get(CmsTemplateContextInfo.SETTING);
378                if (templateContexts == null) {
379                    templateContexts = CmsStringUtil.listAsString(
380                        new ArrayList<String>(
381                            CmsContainerpageController.get().getData().getTemplateContextInfo().getContextLabels().keySet()),
382                        "|");
383                } else if (templateContexts.equals(CmsTemplateContextInfo.EMPTY_VALUE)) {
384                    // translate "none" to an empty selection
385                    templateContexts = "";
386                }
387                m_settings.put(CmsTemplateContextInfo.SETTING, templateContexts);
388
389                CmsFieldSet contextsFieldset = new CmsFieldSet();
390                contextsFieldset.setLegend(m_contextInfo.getSettingDefinition().getNiceName());
391                contextsFieldset.getElement().getStyle().setMarginTop(10, Style.Unit.PX);
392                m_contextsWidget = new CmsMultiCheckBox(
393                    CmsStringUtil.splitAsMap(m_contextInfo.getSettingDefinition().getWidgetConfiguration(), "|", ":"));
394                for (CmsCheckBox checkbox : m_contextsWidget.getCheckboxes()) {
395                    Style checkboxStyle = checkbox.getElement().getStyle();
396                    checkbox.getButton().getElement().getStyle().setFontWeight(Style.FontWeight.NORMAL);
397                    checkboxStyle.setMarginTop(7, Style.Unit.PX);
398                }
399                m_contextsWidget.setFormValueAsString(m_settings.get(CmsTemplateContextInfo.SETTING));
400                m_contextsWidget.addValueChangeHandler(new ValueChangeHandler<String>() {
401
402                    public void onValueChange(ValueChangeEvent<String> event) {
403
404                        setTemplateContextChanged(true);
405                    }
406                });
407                contextsFieldset.add(m_contextsWidget);
408                fieldSetPanel.getMainPanel().add(contextsFieldset);
409            }
410        } else {
411            formFieldPanel = new CmsInfoBoxFormFieldPanel(infoBean);
412        }
413
414        CmsUUID serverId = null;
415        if (elementBean.isModelGroup()) {
416            serverId = elementBean.getModelGroupId();
417        } else {
418            String id = CmsContainerpageController.getServerId(elementBean.getClientId());
419            if (CmsUUID.isValidUUID(id) && !(new CmsUUID(id).isNullUUID())) {
420                serverId = new CmsUUID(id);
421            }
422        }
423        if (serverId != null) {
424            CmsContextMenuButton menuButton = new CmsContextMenuButton(
425                serverId,
426                new CmsDialogContextMenuHandler(),
427                AdeContext.resourceinfo);
428            menuButton.addStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().permaVisible());
429            formFieldPanel.getInfoWidget().addButton(menuButton);
430        }
431
432        getForm().setWidget(formFieldPanel);
433        formFieldPanel.addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().formGradientBackground());
434        I_CmsFormSubmitHandler submitHandler = new I_CmsFormSubmitHandler() {
435
436            /**
437             * @see org.opencms.gwt.client.ui.input.form.I_CmsFormSubmitHandler#onSubmitForm(org.opencms.gwt.client.ui.input.form.CmsForm, java.util.Map, java.util.Set)
438             */
439            public void onSubmitForm(
440                CmsForm formParam,
441                final Map<String, String> fieldValues,
442                Set<String> editedFields) {
443
444                submitForm(formParam, fieldValues, editedFields);
445            }
446        };
447        CmsDialogFormHandler formHandler = new CmsDialogFormHandler();
448        formHandler.setSubmitHandler(submitHandler);
449        getForm().setFormHandler(formHandler);
450        formHandler.setDialog(this);
451        renderSettingsForm(
452            m_elementBean.getSettingConfig(m_containerId),
453            m_elementBean.getFormatterConfig(m_containerId).getNestedFormatterPrefixes());
454    }
455
456    /**
457     * @see org.opencms.gwt.client.ui.input.form.CmsFormDialog#center()
458     */
459    @Override
460    public void center() {
461
462        show();
463    }
464
465    /**
466     * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetMultiFactory#createFormWidget(java.lang.String, java.util.Map, com.google.common.base.Optional)
467     */
468    public I_CmsFormWidget createFormWidget(
469        String key,
470        Map<String, String> widgetParams,
471        Optional<String> defaultValue) {
472
473        if (CmsSelectBox.WIDGET_TYPE.equals(key) || CmsSelectComboBox.WIDGET_TYPE.equals(key)) {
474            if ((defaultValue != null) && defaultValue.isPresent() && widgetParams.containsKey(defaultValue.get())) {
475                key = key + CmsSelectBox.NOTNULL_SUFFIX;
476            }
477            Map<String, String> newParams = new HashMap<>();
478            newParams.putAll(widgetParams);
479            newParams.put(CmsSelectBox.OPTION_RESIZABLE, "false");
480            widgetParams = newParams;
481        }
482
483        return CmsWidgetFactoryRegistry.instance().createFormWidget(key, widgetParams, defaultValue);
484    }
485
486    /**
487     * @see com.google.gwt.user.client.ui.PopupPanel#setPopupPosition(int, int)
488     */
489    @Override
490    public void setPopupPosition(int left, int top) {
491
492        // positioning handled via CSS
493    }
494
495    /**
496     * @see org.opencms.gwt.client.ui.input.form.CmsFormDialog#show()
497     */
498    @Override
499    public void show() {
500
501        super.show();
502        // positioning handled by CSS
503        getElement().getStyle().clearPosition();
504        getElement().getStyle().clearLeft();
505        getElement().getStyle().clearTop();
506
507    }
508
509    /**
510     * Returns if the template context has been changed.<p>
511     *
512     * @return <code>true</code> if the template context has been changed
513     */
514    boolean isTemplateContextChanged() {
515
516        return m_changedContext;
517    }
518
519    /**
520     * Handles the formatter selection changes.<p>
521     *
522     * @param formatterId the formatter id
523     */
524    void onFormatterChange(String formatterId) {
525
526        m_formatter = formatterId;
527        CmsFormatterConfig config = m_elementBean.getFormatters().get(m_containerId).get(formatterId);
528        renderSettingsForm(config.getSettingConfig(), config.getNestedFormatterPrefixes());
529    }
530
531    /**
532     * Renders the settings form.<p>
533     *
534     * @param settingsConfig the settings configuration
535     * @param nestedFormatterPrefixes the nested formatter prefixes
536     */
537    void renderSettingsForm(
538        Map<String, CmsXmlContentProperty> settingsConfig,
539        Map<String, String> nestedFormatterPrefixes) {
540
541        Map<String, String> presets = m_presets;
542        if (presets == null) {
543            presets = new HashMap<String, String>();
544        }
545        List<String> groups = new ArrayList<String>(getForm().getGroups());
546        for (String group : groups) {
547            getForm().removeGroup(group);
548        }
549
550        CmsFieldsetFormFieldPanel formFieldPanel = null;
551        if (getForm().getWidget() instanceof CmsFieldsetFormFieldPanel) {
552            formFieldPanel = ((CmsFieldsetFormFieldPanel)getForm().getWidget());
553        }
554        if ((formFieldPanel != null) && (nestedFormatterPrefixes != null) && !nestedFormatterPrefixes.isEmpty()) {
555            for (Entry<String, String> entry : nestedFormatterPrefixes.entrySet()) {
556                CmsFieldSet fieldSet = new CmsFieldSet();
557                fieldSet.setLegend(entry.getValue());
558                fieldSet.getElement().getStyle().setMarginTop(10, Style.Unit.PX);
559                formFieldPanel.addGroupFieldSet(entry.getKey(), fieldSet);
560            }
561        }
562        // using LinkedHashMap to preserve the order
563        Map<String, I_CmsFormField> formFields = new LinkedHashMap<String, I_CmsFormField>();
564        for (CmsXmlContentProperty propConfig : settingsConfig.values()) {
565            if (m_presets.containsKey(propConfig.getName())) {
566                // settings configured as presets on the container are not user-editable
567                continue;
568            }
569            CmsBasicFormField currentField = CmsBasicFormField.createField(
570                propConfig,
571                propConfig.getName(),
572                this,
573                Collections.<String, String> emptyMap(),
574                false);
575            formFields.put(propConfig.getName(), currentField);
576
577        }
578        for (I_CmsFormField field : formFields.values()) {
579
580            String fieldId = field.getId();
581            CmsXmlContentProperty propDef = settingsConfig.get(fieldId);
582            // skip hidden fields
583            if (!HIDDEN_FIELD_WIDGET.equals(propDef.getWidget())) {
584                String initialValue = m_settings.get(fieldId);
585                if (initialValue == null) {
586
587                    initialValue = propDef.getDefault();
588                }
589                String group = "";
590                if ((nestedFormatterPrefixes != null) && !nestedFormatterPrefixes.isEmpty()) {
591                    for (String prefix : nestedFormatterPrefixes.keySet()) {
592                        if (fieldId.startsWith(prefix)) {
593                            group = prefix;
594                            break;
595                        }
596                    }
597                }
598
599                getForm().addField(group, field, initialValue);
600            }
601        }
602        getForm().render();
603    }
604
605    /**
606     * Sets the template context changed flag.<p>
607     * @param changed the template context changed flag
608     */
609    void setTemplateContextChanged(boolean changed) {
610
611        m_changedContext = changed;
612    }
613
614    /**
615     * Submits the settings form.<p>
616     *
617     * @param formParam the form
618     * @param fieldValues the field values
619     * @param editedFields the changed fields
620     */
621    void submitForm(CmsForm formParam, final Map<String, String> fieldValues, Set<String> editedFields) {
622
623        String modelGroupId = null;
624
625        if (CmsInheritanceContainerEditor.getInstance() != null) {
626            CmsInheritanceContainerEditor.getInstance().onSettingsEdited();
627        }
628        if (m_contextsWidget != null) {
629            String newTemplateContexts = m_contextsWidget.getFormValueAsString();
630            if ((newTemplateContexts == null) || "".equals(newTemplateContexts)) {
631                newTemplateContexts = CmsTemplateContextInfo.EMPTY_VALUE;
632                // translate an empty selection to "none"
633            }
634            fieldValues.put(CmsTemplateContextInfo.SETTING, newTemplateContexts);
635        }
636        final boolean hasFormatterChanges;
637        if (m_formatterSelect != null) {
638            fieldValues.put(
639                CmsFormatterConfig.getSettingsKeyForContainer(m_containerId),
640                m_formatterSelect.getFormValueAsString());
641            hasFormatterChanges = true;
642        } else {
643            hasFormatterChanges = false;
644        }
645        if (m_createNewCheckBox != null) {
646            m_elementWidget.setCreateNew(m_createNewCheckBox.isChecked());
647            fieldValues.put(CmsContainerElement.CREATE_AS_NEW, Boolean.toString(m_createNewCheckBox.isChecked()));
648        }
649        if (m_modelGroupSelect != null) {
650            GroupOption group = GroupOption.valueOf(m_modelGroupSelect.getFormValueAsString());
651            switch (group) {
652                case disabled:
653                    fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.noGroup.name());
654                    fieldValues.put(CmsContainerElement.USE_AS_COPY_MODEL, Boolean.toString(false));
655                    break;
656                case copy:
657                    fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.isModelGroup.name());
658                    fieldValues.put(CmsContainerElement.USE_AS_COPY_MODEL, Boolean.toString(true));
659                    break;
660                case reuse:
661                    fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.isModelGroup.name());
662                    fieldValues.put(CmsContainerElement.USE_AS_COPY_MODEL, Boolean.toString(false));
663                    break;
664                default:
665                    break;
666            }
667            if (group != GroupOption.disabled) {
668                modelGroupId = CmsContainerpageController.getServerId(m_elementBean.getClientId());
669            }
670        }
671
672        if ((m_modelGroupBreakUp != null) && m_modelGroupBreakUp.isChecked()) {
673            fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.noGroup.name());
674        }
675
676        final Map<String, String> filteredFieldValues = new HashMap<String, String>();
677        for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
678            String key = entry.getKey();
679            String value = entry.getValue();
680            if ((value != null) && (value.length() > 0)) {
681                filteredFieldValues.put(key, value);
682            }
683        }
684        final String changeModelGroupId = modelGroupId;
685        m_controller.reloadElementWithSettings(
686            m_elementWidget,
687            m_elementBean.getClientId(),
688            filteredFieldValues,
689            new I_CmsSimpleCallback<CmsContainerPageElementPanel>() {
690
691                public void execute(CmsContainerPageElementPanel result) {
692
693                    if (isTemplateContextChanged()) {
694                        // if the context multiselect box isn't displayed, of course it can't change values,
695                        // and this code won't be executed.
696                        CmsContainerpageController.get().handleChangeTemplateContext(
697                            result,
698                            filteredFieldValues.get(CmsTemplateContextInfo.SETTING));
699                    }
700                    if (hasFormatterChanges) {
701                        updateCss();
702                    }
703                    if (result.getElement().getInnerHTML().contains(CmsGwtConstants.FORMATTER_RELOAD_MARKER)
704                        && !CmsContainerpageController.get().isGroupcontainerEditing()) {
705                        CmsContainerpageController.get().reloadPage();
706                    }
707                    if (m_modelGroupSelect != null) {
708                        m_controller.setModelGroupElementId(changeModelGroupId);
709                    }
710                }
711
712            });
713    }
714
715    /**
716     * Updates the CSS resources for the selected formatter.<p>
717     */
718    void updateCss() {
719
720        String formatterId = m_formatterSelect.getFormValueAsString();
721        CmsFormatterConfig formatter = m_elementBean.getFormatters().get(m_containerId).get(formatterId);
722        Set<String> cssResources = formatter.getCssResources();
723        for (String cssResource : cssResources) {
724            CmsDomUtil.ensureStyleSheetIncluded(cssResource);
725        }
726        if (formatter.hasInlineCss()) {
727            ensureInlineCss(formatterId, formatter.getInlineCss());
728        }
729    }
730
731    /**
732     * Adds the create new checkbox to the given field set.<p>
733     *
734     * @param elementBean the element bean
735     * @param fieldSet the field set
736     */
737    private void addCreateNewCheckbox(CmsContainerElementData elementBean, CmsFieldSet fieldSet) {
738
739        m_createNewCheckBox = new CmsCheckBox(Messages.get().key(Messages.GUI_CREATE_NEW_LABEL_0));
740        m_createNewCheckBox.setDisplayInline(false);
741        m_createNewCheckBox.getElement().getStyle().setMarginTop(7, Style.Unit.PX);
742        m_createNewCheckBox.setChecked(elementBean.isCreateNew());
743        fieldSet.add(m_createNewCheckBox);
744    }
745
746    /**
747     * Adds the model group settings fields to the given field set.<p>
748     *
749     * @param elementBean the element bean
750     * @param elementWidget the element widget
751     * @param fieldSet the field set
752     */
753    private void addModelGroupSettings(
754        CmsContainerElementData elementBean,
755        CmsContainerPageElementPanel elementWidget,
756        CmsFieldSet fieldSet) {
757
758        Map<String, String> groupOptions = new LinkedHashMap<String, String>();
759        groupOptions.put(GroupOption.disabled.name(), GroupOption.disabled.getLabel());
760        groupOptions.put(GroupOption.copy.name(), GroupOption.copy.getLabel());
761        groupOptions.put(GroupOption.reuse.name(), GroupOption.reuse.getLabel());
762        m_modelGroupSelect = new CmsSelectBox(groupOptions);
763        if (elementWidget.isModelGroup()) {
764            if (Boolean.valueOf(elementBean.getSettings().get(CmsContainerElement.USE_AS_COPY_MODEL)).booleanValue()) {
765                m_modelGroupSelect.selectValue(GroupOption.copy.name());
766            } else {
767                m_modelGroupSelect.selectValue(GroupOption.reuse.name());
768            }
769        }
770        CmsFormRow selectRow = new CmsFormRow();
771        selectRow.getLabel().setText(Messages.get().key(Messages.GUI_USE_AS_MODEL_GROUP_LABEL_0));
772        selectRow.getWidgetContainer().add(m_modelGroupSelect);
773        fieldSet.add(selectRow);
774    }
775
776    /**
777     * Ensures the CSS snippet with the given ID is present.<p>
778     *
779     * @param formatterId the ID
780     * @param cssContent the CSS snippet
781     */
782    private native void ensureInlineCss(String formatterId, String cssContent)/*-{
783                var styles = $wnd.document.styleSheets;
784                for (var i = 0; i < styles.length; i++) {
785                        // IE uses the owningElement property
786                        var styleNode = styles[i].owningElement ? styles[i].owningElement
787                                        : styles[i].ownerNode;
788                        if (styleNode != null && styleNode.rel == formatterId) {
789                                // inline css is present
790                                return;
791                        }
792                }
793                // include inline css into head
794                var headID = $wnd.document.getElementsByTagName("head")[0];
795                var cssNode = $wnd.document.createElement('style');
796                cssNode.type = 'text/css';
797                cssNode.rel = formatterId;
798                if (cssNode.styleSheet) {
799                        // in case of IE
800                        cssNode.styleSheet.cssText = cssContent;
801                } else {
802                        // otherwise
803                        cssNode.appendChild(document.createTextNode(cssContent));
804                }
805                headID.appendChild(cssNode);
806    }-*/;
807}