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    /** The original formatter key. */
226    private String m_originalFormatter;
227
228    /** Setting presets. */
229    private Map<String, String> m_presets;
230
231    /** The element setting values. */
232    private Map<String, String> m_settings;
233
234    /**
235     * Constructor.<p>
236     *
237     * @param controller the container page controller
238     * @param elementWidget the element panel
239     * @param settingsConfig the element setting configuration
240     * @param settingPresets the presets for settings
241     *
242     * @throws NoFormatterException if no formatter configuration is found for the element
243     */
244    public CmsElementSettingsDialog(
245        CmsContainerpageController controller,
246        CmsContainerPageElementPanel elementWidget,
247        CmsElementSettingsConfig settingsConfig,
248        Map<String, String> settingPresets)
249    throws NoFormatterException {
250
251        super(Messages.get().key(Messages.GUI_PROPERTY_DIALOG_TITLE_0), new CmsForm(false), null);
252        setAnimationEnabled(false);
253        setUseAnimation(false);
254        addStyleName(I_CmsLayoutBundle.INSTANCE.elementSettingsDialogCss().elementSettingsDialog());
255        m_presets = settingPresets != null ? settingPresets : new HashMap<String, String>();
256        CmsContainerElementData elementBean = settingsConfig.getElementData();
257        m_elementWidget = elementWidget;
258        m_controller = controller;
259        m_elementBean = elementBean;
260        m_contextInfo = m_controller.getData().getTemplateContextInfo();
261        m_containerId = m_elementWidget.getParentTarget().getContainerId();
262        CmsListInfoBean infoBean = new CmsListInfoBean();
263        infoBean.setResourceState(settingsConfig.getState());
264        infoBean.setTitle(elementBean.getTitle());
265        infoBean.setSubTitle(elementBean.getSitePath());
266        infoBean.setResourceType(elementBean.getResourceType());
267        infoBean.setBigIconClasses(elementBean.getBigIconClasses());
268        m_settings = elementBean.getSettings();
269        A_CmsFormFieldPanel formFieldPanel = null;
270        CmsFormatterConfig currentFormatterConfig = m_elementBean.getFormatterConfig(m_containerId);
271        if (currentFormatterConfig == null) {
272            throw new NoFormatterException();
273        }
274        for (CmsAdditionalInfoBean addInfo : settingsConfig.getAdditionalInfo()) {
275            infoBean.addAdditionalInfo(addInfo.getName(), addInfo.getValue(), addInfo.getStyle());
276        }
277        // infoBean.addAdditionalInfo(Messages.get().key(Messages.GUI_ADDINFO_FORMATTER_PATH_0), formatterPath);
278        I_CmsDropContainer dropContainer = elementWidget.getParentTarget();
279        if (dropContainer instanceof CmsContainerPageContainer) {
280            CmsContainerPageContainer cpc = (CmsContainerPageContainer)dropContainer;
281            String type = cpc.getContainerType();
282            String name = cpc.getContainerId();
283            infoBean.addAdditionalInfo(Messages.get().key(Messages.GUI_ADDINFO_FORMATTER_CONTAINER_0), name);
284            infoBean.addAdditionalInfo(Messages.get().key(Messages.GUI_ADDINFO_FORMATTER_CONTAINER_TYPE_0), type);
285        }
286
287        boolean isEditableModelGroup = CmsCoreProvider.get().getUserInfo().isDeveloper()
288            && m_controller.getData().isModelGroup()
289            && ((m_controller.getModelGroupElementId() == null)
290                || CmsContainerpageController.getServerId(elementBean.getClientId()).equals(
291                    m_controller.getModelGroupElementId()));
292        boolean isDeveloper = CmsCoreProvider.get().getUserInfo().isDeveloper();
293        m_originalFormatter = currentFormatterConfig.getKeyOrId();
294
295        if (m_contextInfo.shouldShowElementTemplateContextSelection()
296            || isDeveloper
297            || m_elementBean.hasAlternativeFormatters(m_containerId)) {
298            CmsFieldsetFormFieldPanel fieldSetPanel = new FieldPanel(
299                infoBean,
300                Messages.get().key(Messages.GUI_SETTINGS_LEGEND_0));
301            formFieldPanel = fieldSetPanel;
302            if (m_elementBean.hasAlternativeFormatters(m_containerId)) {
303                CmsFieldSet formatterFieldset = new CmsFieldSet();
304                // insert as first field-set after the element info box
305                fieldSetPanel.getMainPanel().insert(formatterFieldset, 1);
306                formatterFieldset.setLegend(Messages.get().key(Messages.GUI_FORMATTERS_LEGEND_0));
307                formatterFieldset.getElement().getStyle().setMarginTop(10, Style.Unit.PX);
308                LinkedHashMap<String, String> formatters = new LinkedHashMap<String, String>();
309                CmsElementSettingsFormatterWidget formatterWidget = new CmsElementSettingsFormatterWidget();
310                m_formatterSelect = formatterWidget.getFormatterSelect();
311                CmsFormatterConfigCollection formattersForContainer = m_elementBean.getFormatters().get(m_containerId);
312                for (CmsFormatterConfig formatter : formattersForContainer) {
313                    formatters.put(formatter.getKeyOrId(), formatter.getLabel());
314                    m_formatterSelect.setTitle(formatter.getKeyOrId(), formatter.getJspRootPath());
315                }
316                m_formatterSelect.setItems(formatters);
317                String currentFormatterValue = m_elementBean.getFormatterConfig(m_containerId).getKeyOrId();
318                m_formatter = currentFormatterValue;
319                m_formatterSelect.selectValue(currentFormatterValue);
320                m_formatterSelect.addValueChangeHandler(new ValueChangeHandler<String>() {
321
322                    public void onValueChange(ValueChangeEvent<String> event) {
323
324                        onFormatterChange(event.getValue());
325                    }
326                });
327
328                // set up formatter help tooltip
329                final FlowPanel help = formatterWidget.getHelp();
330                for (String style : CmsFormRow.ICON_STYLES) {
331                    help.addStyleName(style);
332                }
333                final Map<String, CmsFieldTooltip.Data> tooltips = Maps.newHashMap();
334                for (CmsFormatterConfig formatterConfig : formattersForContainer) {
335                    String description = formatterConfig.getDescription();
336                    if (description == null) {
337                        description = formatterConfig.getLabel();
338                    }
339                    tooltips.put(formatterConfig.getKeyOrId(), new Data(help, description, true));
340                }
341                Supplier<CmsFieldTooltip.Data> tooltipProvider = new Supplier<CmsFieldTooltip.Data>() {
342
343                    @SuppressWarnings("synthetic-access")
344                    public Data get() {
345
346                        return tooltips.get(m_formatter);
347                    }
348                };
349                CmsFormRow.installTooltipEventHandlers(help, tooltipProvider);
350                formatterFieldset.add(formatterWidget);
351            }
352            if (m_controller.getData().isModelPage() || isEditableModelGroup) {
353                CmsFieldSet modelGroupFieldSet = new CmsFieldSet();
354                modelGroupFieldSet.setLegend(Messages.get().key(Messages.GUI_CREATE_NEW_LEGEND_0
355
356                ));
357                modelGroupFieldSet.getElement().getStyle().setMarginTop(10, Unit.PX);
358
359                if (isEditableModelGroup && !elementWidget.hasModelGroupParent()) {
360                    addModelGroupSettings(elementBean, elementWidget, modelGroupFieldSet);
361                } else if (!elementWidget.isModelGroup()) {
362                    addCreateNewCheckbox(elementBean, modelGroupFieldSet);
363                }
364                if (modelGroupFieldSet.getWidgetCount() > 0) {
365                    fieldSetPanel.getMainPanel().insert(modelGroupFieldSet, 1);
366                }
367
368            } else if (elementWidget.isModelGroup()) {
369                CmsFieldSet modelGroupFieldSet = new CmsFieldSet();
370                modelGroupFieldSet.setLegend(Messages.get().key(Messages.GUI_CREATE_NEW_LEGEND_0
371
372                ));
373                modelGroupFieldSet.getElement().getStyle().setMarginTop(10, Unit.PX);
374                m_modelGroupBreakUp = new CmsCheckBox(Messages.get().key(Messages.GUI_MODEL_GROUP_BREAK_UP_0));
375                m_modelGroupBreakUp.setDisplayInline(false);
376                m_modelGroupBreakUp.getElement().getStyle().setMarginTop(7, Style.Unit.PX);
377                modelGroupFieldSet.add(m_modelGroupBreakUp);
378                fieldSetPanel.getMainPanel().insert(modelGroupFieldSet, 1);
379            }
380
381            if (m_contextInfo.shouldShowElementTemplateContextSelection()) {
382                String templateContexts = m_settings.get(CmsTemplateContextInfo.SETTING);
383                if (templateContexts == null) {
384                    templateContexts = CmsStringUtil.listAsString(
385                        new ArrayList<String>(
386                            CmsContainerpageController.get().getData().getTemplateContextInfo().getContextLabels().keySet()),
387                        "|");
388                } else if (templateContexts.equals(CmsTemplateContextInfo.EMPTY_VALUE)) {
389                    // translate "none" to an empty selection
390                    templateContexts = "";
391                }
392                m_settings.put(CmsTemplateContextInfo.SETTING, templateContexts);
393
394                CmsFieldSet contextsFieldset = new CmsFieldSet();
395                contextsFieldset.setLegend(m_contextInfo.getSettingDefinition().getNiceName());
396                contextsFieldset.getElement().getStyle().setMarginTop(10, Style.Unit.PX);
397                m_contextsWidget = new CmsMultiCheckBox(
398                    CmsStringUtil.splitAsMap(m_contextInfo.getSettingDefinition().getWidgetConfiguration(), "|", ":"));
399                for (CmsCheckBox checkbox : m_contextsWidget.getCheckboxes()) {
400                    Style checkboxStyle = checkbox.getElement().getStyle();
401                    checkbox.getButton().getElement().getStyle().setFontWeight(Style.FontWeight.NORMAL);
402                    checkboxStyle.setMarginTop(7, Style.Unit.PX);
403                }
404                m_contextsWidget.setFormValueAsString(m_settings.get(CmsTemplateContextInfo.SETTING));
405                m_contextsWidget.addValueChangeHandler(new ValueChangeHandler<String>() {
406
407                    public void onValueChange(ValueChangeEvent<String> event) {
408
409                        setTemplateContextChanged(true);
410                    }
411                });
412                contextsFieldset.add(m_contextsWidget);
413                fieldSetPanel.getMainPanel().add(contextsFieldset);
414            }
415        } else {
416            formFieldPanel = new CmsInfoBoxFormFieldPanel(infoBean);
417        }
418
419        CmsUUID serverId = null;
420        if (elementBean.isModelGroup()) {
421            serverId = elementBean.getModelGroupId();
422        } else {
423            String id = CmsContainerpageController.getServerId(elementBean.getClientId());
424            if (CmsUUID.isValidUUID(id) && !(new CmsUUID(id).isNullUUID())) {
425                serverId = new CmsUUID(id);
426            }
427        }
428        if (serverId != null) {
429            CmsContextMenuButton menuButton = new CmsContextMenuButton(
430                serverId,
431                new CmsDialogContextMenuHandler(),
432                AdeContext.resourceinfo);
433            menuButton.addStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().permaVisible());
434            formFieldPanel.getInfoWidget().addButton(menuButton);
435        }
436
437        getForm().setWidget(formFieldPanel);
438        formFieldPanel.addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().formGradientBackground());
439        I_CmsFormSubmitHandler submitHandler = new I_CmsFormSubmitHandler() {
440
441            /**
442             * @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)
443             */
444            public void onSubmitForm(
445                CmsForm formParam,
446                final Map<String, String> fieldValues,
447                Set<String> editedFields) {
448
449                submitForm(formParam, fieldValues, editedFields);
450            }
451        };
452        CmsDialogFormHandler formHandler = new CmsDialogFormHandler();
453        formHandler.setSubmitHandler(submitHandler);
454        getForm().setFormHandler(formHandler);
455        formHandler.setDialog(this);
456        renderSettingsForm(
457            m_elementBean.getSettingConfig(m_containerId),
458            m_elementBean.getFormatterConfig(m_containerId).getNestedFormatterPrefixes());
459    }
460
461    /**
462     * @see org.opencms.gwt.client.ui.input.form.CmsFormDialog#center()
463     */
464    @Override
465    public void center() {
466
467        show();
468    }
469
470    /**
471     * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetMultiFactory#createFormWidget(java.lang.String, java.util.Map, com.google.common.base.Optional)
472     */
473    public I_CmsFormWidget createFormWidget(
474        String key,
475        Map<String, String> widgetParams,
476        Optional<String> defaultValue) {
477
478        if (CmsSelectBox.WIDGET_TYPE.equals(key) || CmsSelectComboBox.WIDGET_TYPE.equals(key)) {
479            if ((defaultValue != null) && defaultValue.isPresent() && widgetParams.containsKey(defaultValue.get())) {
480                key = key + CmsSelectBox.NOTNULL_SUFFIX;
481            }
482            Map<String, String> newParams = new HashMap<>();
483            newParams.putAll(widgetParams);
484            newParams.put(CmsSelectBox.OPTION_RESIZABLE, "false");
485            widgetParams = newParams;
486        }
487
488        return CmsWidgetFactoryRegistry.instance().createFormWidget(key, widgetParams, defaultValue);
489    }
490
491    /**
492     * @see com.google.gwt.user.client.ui.PopupPanel#setPopupPosition(int, int)
493     */
494    @Override
495    public void setPopupPosition(int left, int top) {
496
497        // positioning handled via CSS
498    }
499
500    /**
501     * @see org.opencms.gwt.client.ui.input.form.CmsFormDialog#show()
502     */
503    @Override
504    public void show() {
505
506        super.show();
507        // positioning handled by CSS
508        getElement().getStyle().clearPosition();
509        getElement().getStyle().clearLeft();
510        getElement().getStyle().clearTop();
511
512    }
513
514    /**
515     * Returns if the template context has been changed.<p>
516     *
517     * @return <code>true</code> if the template context has been changed
518     */
519    boolean isTemplateContextChanged() {
520
521        return m_changedContext;
522    }
523
524    /**
525     * Handles the formatter selection changes.<p>
526     *
527     * @param formatterId the formatter id
528     */
529    void onFormatterChange(String formatterId) {
530
531        m_formatter = formatterId;
532        CmsFormatterConfig config = m_elementBean.getFormatters().get(m_containerId).get(formatterId);
533        renderSettingsForm(config.getSettingConfig(), config.getNestedFormatterPrefixes());
534    }
535
536    /**
537     * Renders the settings form.<p>
538     *
539     * @param settingsConfig the settings configuration
540     * @param nestedFormatterPrefixes the nested formatter prefixes
541     */
542    void renderSettingsForm(
543        Map<String, CmsXmlContentProperty> settingsConfig,
544        Map<String, String> nestedFormatterPrefixes) {
545
546        Map<String, String> presets = m_presets;
547        if (presets == null) {
548            presets = new HashMap<String, String>();
549        }
550        List<String> groups = new ArrayList<String>(getForm().getGroups());
551        for (String group : groups) {
552            getForm().removeGroup(group);
553        }
554
555        CmsFieldsetFormFieldPanel formFieldPanel = null;
556        if (getForm().getWidget() instanceof CmsFieldsetFormFieldPanel) {
557            formFieldPanel = ((CmsFieldsetFormFieldPanel)getForm().getWidget());
558        }
559        if ((formFieldPanel != null) && (nestedFormatterPrefixes != null) && !nestedFormatterPrefixes.isEmpty()) {
560            for (Entry<String, String> entry : nestedFormatterPrefixes.entrySet()) {
561                CmsFieldSet fieldSet = new CmsFieldSet();
562                fieldSet.setLegend(entry.getValue());
563                fieldSet.getElement().getStyle().setMarginTop(10, Style.Unit.PX);
564                formFieldPanel.addGroupFieldSet(entry.getKey(), fieldSet);
565            }
566        }
567        // using LinkedHashMap to preserve the order
568        Map<String, I_CmsFormField> formFields = new LinkedHashMap<String, I_CmsFormField>();
569        for (CmsXmlContentProperty propConfig : settingsConfig.values()) {
570            if (m_presets.containsKey(propConfig.getName())) {
571                // settings configured as presets on the container are not user-editable
572                continue;
573            }
574            CmsBasicFormField currentField = CmsBasicFormField.createField(
575                propConfig,
576                propConfig.getName(),
577                this,
578                Collections.<String, String> emptyMap(),
579                false);
580            formFields.put(propConfig.getName(), currentField);
581
582        }
583        for (I_CmsFormField field : formFields.values()) {
584
585            String fieldId = field.getId();
586            CmsXmlContentProperty propDef = settingsConfig.get(fieldId);
587            // skip hidden fields
588            if (!HIDDEN_FIELD_WIDGET.equals(propDef.getWidget())) {
589                String initialValue = m_settings.get(fieldId);
590                if (initialValue == null) {
591
592                    initialValue = propDef.getDefault();
593                }
594                String group = "";
595                if ((nestedFormatterPrefixes != null) && !nestedFormatterPrefixes.isEmpty()) {
596                    for (String prefix : nestedFormatterPrefixes.keySet()) {
597                        if (fieldId.startsWith(prefix)) {
598                            group = prefix;
599                            break;
600                        }
601                    }
602                }
603
604                getForm().addField(group, field, initialValue);
605            }
606        }
607        getForm().render();
608    }
609
610    /**
611     * Sets the template context changed flag.<p>
612     * @param changed the template context changed flag
613     */
614    void setTemplateContextChanged(boolean changed) {
615
616        m_changedContext = changed;
617    }
618
619    /**
620     * Submits the settings form.<p>
621     *
622     * @param formParam the form
623     * @param fieldValues the field values
624     * @param editedFields the changed fields
625     */
626    void submitForm(CmsForm formParam, final Map<String, String> fieldValues, Set<String> editedFields) {
627
628        String modelGroupId = null;
629
630        if (CmsInheritanceContainerEditor.getInstance() != null) {
631            CmsInheritanceContainerEditor.getInstance().onSettingsEdited();
632        }
633        if (m_contextsWidget != null) {
634            String newTemplateContexts = m_contextsWidget.getFormValueAsString();
635            if ((newTemplateContexts == null) || "".equals(newTemplateContexts)) {
636                newTemplateContexts = CmsTemplateContextInfo.EMPTY_VALUE;
637                // translate an empty selection to "none"
638            }
639            fieldValues.put(CmsTemplateContextInfo.SETTING, newTemplateContexts);
640        }
641        final boolean hasFormatterChanges;
642        if (m_formatterSelect != null) {
643            fieldValues.put(
644                CmsFormatterConfig.getSettingsKeyForContainer(m_containerId),
645                m_formatterSelect.getFormValueAsString());
646            hasFormatterChanges = true;
647        } else {
648            hasFormatterChanges = false;
649            if (m_originalFormatter != null) {
650                // in case there is only 1 formatter, we still want to send the formatter key to the server to avoid cases
651                // where the element is removed because no default formatter can be found in the active sitemap config.
652                fieldValues.put(CmsFormatterConfig.getSettingsKeyForContainer(m_containerId), m_originalFormatter);
653            }
654        }
655        if (m_createNewCheckBox != null) {
656            m_elementWidget.setCreateNew(m_createNewCheckBox.isChecked());
657            fieldValues.put(CmsContainerElement.CREATE_AS_NEW, Boolean.toString(m_createNewCheckBox.isChecked()));
658        }
659        if (m_modelGroupSelect != null) {
660            GroupOption group = GroupOption.valueOf(m_modelGroupSelect.getFormValueAsString());
661            switch (group) {
662                case disabled:
663                    fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.noGroup.name());
664                    fieldValues.put(CmsContainerElement.USE_AS_COPY_MODEL, Boolean.toString(false));
665                    break;
666                case copy:
667                    fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.isModelGroup.name());
668                    fieldValues.put(CmsContainerElement.USE_AS_COPY_MODEL, Boolean.toString(true));
669                    break;
670                case reuse:
671                    fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.isModelGroup.name());
672                    fieldValues.put(CmsContainerElement.USE_AS_COPY_MODEL, Boolean.toString(false));
673                    break;
674                default:
675                    break;
676            }
677            if (group != GroupOption.disabled) {
678                modelGroupId = CmsContainerpageController.getServerId(m_elementBean.getClientId());
679            }
680        }
681
682        if ((m_modelGroupBreakUp != null) && m_modelGroupBreakUp.isChecked()) {
683            fieldValues.put(CmsContainerElement.MODEL_GROUP_STATE, ModelGroupState.noGroup.name());
684        }
685
686        final Map<String, String> filteredFieldValues = new HashMap<String, String>();
687        for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
688            String key = entry.getKey();
689            String value = entry.getValue();
690            if ((value != null) && (value.length() > 0)) {
691                filteredFieldValues.put(key, value);
692            }
693        }
694        final String changeModelGroupId = modelGroupId;
695        m_controller.reloadElementWithSettings(
696            m_elementWidget,
697            m_elementBean.getClientId(),
698            filteredFieldValues,
699            new I_CmsSimpleCallback<CmsContainerPageElementPanel>() {
700
701                public void execute(CmsContainerPageElementPanel result) {
702
703                    if (isTemplateContextChanged()) {
704                        // if the context multiselect box isn't displayed, of course it can't change values,
705                        // and this code won't be executed.
706                        CmsContainerpageController.get().handleChangeTemplateContext(
707                            result,
708                            filteredFieldValues.get(CmsTemplateContextInfo.SETTING));
709                    }
710                    if (hasFormatterChanges) {
711                        updateCss();
712                    }
713                    if (result.getElement().getInnerHTML().contains(CmsGwtConstants.FORMATTER_RELOAD_MARKER)
714                        && !CmsContainerpageController.get().isGroupcontainerEditing()) {
715                        CmsContainerpageController.get().reloadPage();
716                    }
717                    if (m_modelGroupSelect != null) {
718                        m_controller.setModelGroupElementId(changeModelGroupId);
719                    }
720                }
721
722            });
723    }
724
725    /**
726     * Updates the CSS resources for the selected formatter.<p>
727     */
728    void updateCss() {
729
730        String formatterId = m_formatterSelect.getFormValueAsString();
731        CmsFormatterConfig formatter = m_elementBean.getFormatters().get(m_containerId).get(formatterId);
732        Set<String> cssResources = formatter.getCssResources();
733        for (String cssResource : cssResources) {
734            CmsDomUtil.ensureStyleSheetIncluded(cssResource);
735        }
736        if (formatter.hasInlineCss()) {
737            ensureInlineCss(formatterId, formatter.getInlineCss());
738        }
739    }
740
741    /**
742     * Adds the create new checkbox to the given field set.<p>
743     *
744     * @param elementBean the element bean
745     * @param fieldSet the field set
746     */
747    private void addCreateNewCheckbox(CmsContainerElementData elementBean, CmsFieldSet fieldSet) {
748
749        m_createNewCheckBox = new CmsCheckBox(Messages.get().key(Messages.GUI_CREATE_NEW_LABEL_0));
750        m_createNewCheckBox.setDisplayInline(false);
751        m_createNewCheckBox.getElement().getStyle().setMarginTop(7, Style.Unit.PX);
752        m_createNewCheckBox.setChecked(elementBean.isCreateNew());
753        fieldSet.add(m_createNewCheckBox);
754    }
755
756    /**
757     * Adds the model group settings fields to the given field set.<p>
758     *
759     * @param elementBean the element bean
760     * @param elementWidget the element widget
761     * @param fieldSet the field set
762     */
763    private void addModelGroupSettings(
764        CmsContainerElementData elementBean,
765        CmsContainerPageElementPanel elementWidget,
766        CmsFieldSet fieldSet) {
767
768        Map<String, String> groupOptions = new LinkedHashMap<String, String>();
769        groupOptions.put(GroupOption.disabled.name(), GroupOption.disabled.getLabel());
770        groupOptions.put(GroupOption.copy.name(), GroupOption.copy.getLabel());
771        groupOptions.put(GroupOption.reuse.name(), GroupOption.reuse.getLabel());
772        m_modelGroupSelect = new CmsSelectBox(groupOptions);
773        if (elementWidget.isModelGroup()) {
774            if (Boolean.valueOf(elementBean.getSettings().get(CmsContainerElement.USE_AS_COPY_MODEL)).booleanValue()) {
775                m_modelGroupSelect.selectValue(GroupOption.copy.name());
776            } else {
777                m_modelGroupSelect.selectValue(GroupOption.reuse.name());
778            }
779        }
780        CmsFormRow selectRow = new CmsFormRow();
781        selectRow.getLabel().setText(Messages.get().key(Messages.GUI_USE_AS_MODEL_GROUP_LABEL_0));
782        selectRow.getWidgetContainer().add(m_modelGroupSelect);
783        fieldSet.add(selectRow);
784    }
785
786    /**
787     * Ensures the CSS snippet with the given ID is present.<p>
788     *
789     * @param formatterId the ID
790     * @param cssContent the CSS snippet
791     */
792    private native void ensureInlineCss(String formatterId, String cssContent)/*-{
793                var styles = $wnd.document.styleSheets;
794                for (var i = 0; i < styles.length; i++) {
795                        // IE uses the owningElement property
796                        var styleNode = styles[i].owningElement ? styles[i].owningElement
797                                        : styles[i].ownerNode;
798                        if (styleNode != null && styleNode.rel == formatterId) {
799                                // inline css is present
800                                return;
801                        }
802                }
803                // include inline css into head
804                var headID = $wnd.document.getElementsByTagName("head")[0];
805                var cssNode = $wnd.document.createElement('style');
806                cssNode.type = 'text/css';
807                cssNode.rel = formatterId;
808                if (cssNode.styleSheet) {
809                        // in case of IE
810                        cssNode.styleSheet.cssText = cssContent;
811                } else {
812                        // otherwise
813                        cssNode.appendChild(document.createTextNode(cssContent));
814                }
815                headID.appendChild(cssNode);
816    }-*/;
817}