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.sitemap.client.edit; 029 030import org.opencms.ade.sitemap.client.Messages; 031import org.opencms.gwt.client.property.A_CmsPropertyEditor; 032import org.opencms.gwt.client.property.I_CmsPropertyEditorHandler; 033import org.opencms.gwt.client.ui.input.I_CmsFormWidget; 034import org.opencms.gwt.client.ui.input.I_CmsHasGhostValue; 035import org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel; 036import org.opencms.gwt.client.ui.input.form.CmsBasicFormField; 037import org.opencms.gwt.client.ui.input.form.CmsInfoBoxFormFieldPanel; 038import org.opencms.gwt.shared.property.CmsClientProperty; 039import org.opencms.gwt.shared.property.CmsPathValue; 040import org.opencms.util.CmsStringUtil; 041import org.opencms.xml.content.CmsXmlContentProperty; 042 043import java.util.ArrayList; 044import java.util.Arrays; 045import java.util.Collections; 046import java.util.List; 047import java.util.Map; 048 049import com.google.gwt.user.client.ui.Widget; 050 051/** 052 * Sitemap entry editor class for the navigation mode.<p> 053 * 054 * @since 8.0.0 055 */ 056public class CmsNavModePropertyEditor extends A_CmsPropertyEditor { 057 058 /** The 'split mode' to use for rendering fields. For some property fields, we may want to render two fields, one for the folder and one for the index.html, and this enum is used to tell the rendering function which we are currently rendering. */ 059 enum SplitMode { 060 /** The property is not split. */ 061 none, 062 063 /** The property is split, and we are rendering the field for the parent folder. */ 064 parent, 065 066 /** The property is split, and we are rendering the field for the index.html. */ 067 child; 068 } 069 070 /** 071 * Creates a new instance.<p> 072 * 073 * @param propertyConfig the property configuration 074 * @param handler the entry editor handler 075 */ 076 public CmsNavModePropertyEditor( 077 Map<String, CmsXmlContentProperty> propertyConfig, 078 I_CmsPropertyEditorHandler handler) { 079 080 super(propertyConfig, handler); 081 } 082 083 /** 084 * @see org.opencms.gwt.client.property.A_CmsPropertyEditor#buildFields() 085 */ 086 @Override 087 public void buildFields() { 088 089 Map<String, CmsClientProperty> ownProps = m_handler.getOwnProperties(); 090 Map<String, CmsClientProperty> defaultFileProps = m_handler.getDefaultFileProperties(); 091 092 String entryId = m_handler.getId().toString(); 093 String defaultFileId = toStringOrNull(m_handler.getDefaultFileId()); 094 boolean splitTitle = false; 095 String navText = ""; 096 String title = ""; 097 for (String key : Arrays.asList(CmsClientProperty.PROPERTY_NAVTEXT, CmsClientProperty.PROPERTY_TITLE)) { 098 CmsClientProperty prop = ownProps.get(key); 099 if (prop != null) { 100 String value = prop.getEffectiveValue(); 101 if (value == null) { 102 value = ""; 103 } 104 if (CmsClientProperty.PROPERTY_NAVTEXT.equals(key)) { 105 navText = value; 106 } else { 107 title = value; 108 } 109 } 110 } 111 // if we have both a folder and a default file and either the navtext is different from the title, 112 // or the title is empty, split title field into two fields, one for the folder and one for the default file 113 splitTitle = (defaultFileId != null) && !(navText.equals(title) || "".equals(title)); 114 115 List<String> keys = new ArrayList<String>(m_propertyConfig.keySet()); 116 moveToTop(keys, CmsClientProperty.PROPERTY_NAVTEXT); 117 moveToTop(keys, CmsClientProperty.PROPERTY_DESCRIPTION); 118 moveToTop(keys, CmsClientProperty.PROPERTY_TITLE); 119 for (String propName : keys) { 120 if (splitTitle && CmsClientProperty.PROPERTY_TITLE.equals(propName)) { 121 for (SplitMode mode : Arrays.asList(SplitMode.parent, SplitMode.child)) { 122 buildSimpleField(entryId, defaultFileId, ownProps, defaultFileProps, propName, mode); 123 } 124 } else { 125 buildSimpleField(entryId, defaultFileId, ownProps, defaultFileProps, propName, SplitMode.none); 126 } 127 128 } 129 } 130 131 /** 132 * @see org.opencms.gwt.client.property.A_CmsPropertyEditor#setupFieldContainer() 133 */ 134 @Override 135 protected void setupFieldContainer() { 136 137 m_form.setWidget(new CmsInfoBoxFormFieldPanel(m_handler.getPageInfo())); 138 } 139 140 /** 141 * Builds a single form field.<p> 142 * 143 144 * @param entryId the entry id 145 * @param defaultFileId the default file id 146 * @param ownProps the entry's own properties 147 * @param defaultFileProps the default file properties 148 * @param propName the property name 149 */ 150 private void buildSimpleField( 151 String entryId, 152 String defaultFileId, 153 Map<String, CmsClientProperty> ownProps, 154 Map<String, CmsClientProperty> defaultFileProps, 155 String propName, 156 SplitMode splitMode) { 157 158 CmsXmlContentProperty propDef = m_propertyConfig.get(propName); 159 CmsClientProperty fileProp = defaultFileProps == null ? null : defaultFileProps.get(propName); 160 CmsClientProperty ownProp = ownProps.get(propName); 161 CmsPathValue pathValue = null; 162 if (splitMode == SplitMode.parent) { 163 if (ownProp != null) { 164 pathValue = ownProp.getPathValue().prepend(entryId + "/" + propName); 165 } else { 166 pathValue = new CmsPathValue( 167 "", 168 entryId + "/" + propName + "/" + CmsClientProperty.PATH_STRUCTURE_VALUE); 169 } 170 } else if (splitMode == SplitMode.child) { 171 if (fileProp != null) { 172 pathValue = fileProp.getPathValue().prepend(defaultFileId + "/" + propName); 173 } else { 174 pathValue = new CmsPathValue( 175 "", 176 defaultFileId + "/" + propName + "/" + CmsClientProperty.PATH_STRUCTURE_VALUE); 177 } 178 } else { 179 if (!CmsClientProperty.isPropertyEmpty(fileProp)) { 180 pathValue = fileProp.getPathValue().prepend(defaultFileId + "/" + propName); 181 } else if (!CmsClientProperty.isPropertyEmpty(ownProp)) { 182 pathValue = ownProp.getPathValue().prepend(entryId + "/" + propName); 183 } else { 184 String targetId = null; 185 if (propDef.isPreferFolder() || (m_handler.getDefaultFileId() == null)) { 186 targetId = entryId; 187 } else { 188 targetId = m_handler.getDefaultFileId().toString(); 189 } 190 pathValue = new CmsPathValue( 191 "", 192 targetId + "/" + propName + "/" + CmsClientProperty.PATH_STRUCTURE_VALUE); 193 } 194 } 195 boolean alwaysAllowEmpty = !propName.equals(CmsClientProperty.PROPERTY_NAVTEXT); 196 //CHECK: should we really generally allow empty fields other than NavText to be empty? 197 198 CmsBasicFormField field = CmsBasicFormField.createField( 199 propDef, 200 pathValue.getPath(), 201 this, 202 Collections.<String, String> emptyMap(), 203 alwaysAllowEmpty); 204 CmsClientProperty inheritedProperty = m_handler.getInheritedProperty(propName); 205 String inherited = (inheritedProperty == null) ? null : inheritedProperty.getEffectiveValue(); 206 if (inheritedProperty != null) { 207 String message = Messages.get().key( 208 Messages.GUI_PROPERTY_ORIGIN_2, 209 inheritedProperty.getOrigin(), 210 inherited); 211 ((Widget)field.getWidget()).setTitle(message); 212 } 213 I_CmsFormWidget w = field.getWidget(); 214 // model binding not necessary here 215 String initialValue = pathValue.getValue(); 216 217 boolean ghost = CmsStringUtil.isEmptyOrWhitespaceOnly(pathValue.getValue()); 218 if (w instanceof I_CmsHasGhostValue) { 219 ((I_CmsHasGhostValue)w).setGhostValue(inherited, ghost); 220 if (ghost) { 221 initialValue = null; 222 } 223 } 224 if (ghost && (inheritedProperty != null)) { 225 String message = org.opencms.gwt.client.Messages.get().key( 226 org.opencms.gwt.client.Messages.GUI_ORIGIN_INHERITED_1, 227 inheritedProperty.getOrigin()); 228 field.getLayoutData().put("info", message); 229 } 230 if (splitMode == SplitMode.parent) { 231 field.getLayoutData().put(A_CmsFormFieldPanel.LAYOUT_TAG, Messages.get().key(Messages.GUI_TAG_FOLDER_0)); 232 } else if (splitMode == SplitMode.child) { 233 234 String path = m_handler.getDefaultFilePath(); 235 int slashPos = path.lastIndexOf("/"); 236 String name = slashPos > -1 ? path.substring(slashPos + 1) : path; 237 if (!name.toLowerCase().endsWith(".html")) { 238 name = "index.html"; 239 } 240 field.getLayoutData().put(A_CmsFormFieldPanel.LAYOUT_TAG, name); 241 } 242 243 m_form.addField(m_form.getWidget().getDefaultGroup(), field, initialValue); 244 } 245 246 /** 247 * Moves the given property name to the top of the keys if present.<p> 248 * 249 * @param keys the list of keys 250 * @param propertyName the property name to move 251 */ 252 private void moveToTop(List<String> keys, String propertyName) { 253 254 if (keys.contains(propertyName)) { 255 keys.remove(propertyName); 256 keys.add(0, propertyName); 257 } 258 } 259 260 /** 261 * Helper method which converts an object to a string and returns null if it is null.<p> 262 * 263 * @param obj the object for which to return the string 264 * 265 * @return the string representation or null 266 */ 267 private String toStringOrNull(Object obj) { 268 269 return obj == null ? null : obj.toString(); 270 } 271 272}