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